This R notebook contains the code used to create the figures in the paper: “Interactions among anthropogenic stressors in freshwater ecosystems: a systematic review of 2,396 multiple-stressor experiments” by James A. Orr, Samuel J. Macaulay, Adriana Mordente, Benjamin Burgess, Dania Albini, Julia G. Hunn, Katherin Restrepo-Sulez, Ramesh Wilson, Anne Schechner, Aoife M. Robertson, Bethany Lee, Blake Stuparyk, Delezia Singh, Isobel O’Loughlin, Jeremy J. Piggott, Jiangqiu Zhu, Khuong V. Dinh, Louise C. Archer, Marcin Penk, Minh Thi Thuy Vu, Noël P.D. Juvigny-Kkenafou, Peiyu Zhang, Philip Sanders, Ralf B. Schäfer, Rolf Vinebrooke, Sabine Hilt, Thomas Reed, Michelle C. Jackson.

Set-up

# R version 4.3.1 (2023-06-16)

rm(list = ls())           # clear the environment 

# Packages
library(sf)               # classes and functions for vector data
library(raster)           # classes and functions for raster data
library(tidyverse)        # organising and manipulating data
library(spData)           # for world shapefile 
library(ggVennDiagram)    # for venn diagram figure
library(igraph)           # to create co-occurrence network 
library(knitr)            # to create nice tables
library(reshape2)         # for the melt function 
library(magick)           # for making gifs 
library(ggstream)         # for proportion plots
library(gridExtra)        # for arranging multiple ggplots

The experiments dataset contains 2396 rows, one for each experiment. The combinations dataset contains 4712 rows, one for each combination of stressors, which we use for the co-occurrence analysis. The SpecificCombinations column in the experiments dataset contains the coding used to create the combinations. A description of all of the columns can be found in the supporting information of the paper.

Figure 1 - Overview

# all lower case first
experiments$Country <- tolower(experiments$Country)

# organise experiment data
countries <- experiments %>%
  mutate(counts = 1) %>%
  group_by(Country) %>%
  summarise(experiments = sum(counts)) %>%
  rename(name_long = Country)

# Mercator - epsg: 3857
# Mollweide - `st_crs('ESRI:54009')`
# Robinson - `st_crs('ESRI:54030')`
# Winkel Triple - `st_crs('ESRI:54019')`

# load country shapes
world <- st_transform(spData::world, st_crs('ESRI:54019')) 

# cleaning to make the dataframes consistent
world$name_long <- tolower(world$name_long)
countries$name_long <- tolower(countries$name_long)
countries$name_long <-replace(countries$name_long,
                           countries$name_long=="russia", "russian federation")
countries$name_long <-replace(countries$name_long,
                           countries$name_long=="the netherlands", "netherlands")
countries$name_long <-replace(countries$name_long,
                           countries$name_long=="uk", "united kingdom")
countries$name_long <-replace(countries$name_long,
                           countries$name_long=="usa", "united states")
countries$name_long <-replace(countries$name_long,
                           countries$name_long=="slovak republic", "slovakia")

# join experiment data to countries 
world <- world %>%
  left_join(countries, by = "name_long") %>%
  select(name_long, experiments)

# List of items
x <- list(Physiological = which(experiments$Physiological == "yes"),
          Individual = which(experiments$Individual == "yes"), 
          Population = which(experiments$Population == "yes"),
          Community = which(experiments$Community == "yes"),
          Ecosystem = which(experiments$Ecosystem == "yes"))

# Venn diagram
ggVennDiagram(x, label = "count", label_alpha = 0, edge_size = 0,
              label_size = 3,
              category.names = c("Phy.",
                                 "Ind.",
                                 "Pop.", 
                                 "Com.",
                                 "Eco.")) +
  
  labs(fill = "experiments") +
  
  scale_fill_gradient(low = rgb(0.8, 0.8, 0.8), 
                      high = rgb(0.4, 0.4, 0.4), trans = 'sqrt') +
  
  scale_color_manual(values = c("grey30", "grey30", "grey30", "grey30", "grey30"))

  
rm(x)
Warning: The `size` argument of `element_line()` is deprecated as of ggplot2 3.4.0.
Please use the `linewidth` argument instead.

Warning: NAs introduced by coercion

Joining with `by = join_by(Year)`
# Define the year intervals
year_intervals <- c(1970, 1980, 1990, 2000, 2010, 2020)

# Calculate annual growth rates for experiments and WOS.Biology within each interval
annual_growth_rates <- data.frame()

for (i in 1:(length(year_intervals) - 1)) {
  start_year <- year_intervals[i]
  end_year <- year_intervals[i + 1]
  
  interval_growth_rates <- experiments_year %>%
    filter(Year >= start_year, Year < end_year) %>%
    summarise(experiments_growth = (((last(experiments)/first(experiments))^(1/10)) - 1) * 100,
              wos_growth = (((last(WOS.Biology)/first(WOS.Biology))^(1/10)) - 1) * 100)
  
  annual_growth_rates <- bind_rows(annual_growth_rates, interval_growth_rates)
}

# Extract and return the annual growth rates as vectors
experiments_growth_rates <- annual_growth_rates$experiments_growth
wos_growth_rates <- annual_growth_rates$wos_growth

experiments_growth_rates
[1]      Inf      Inf 25.24845 12.33498 10.95004
wos_growth_rates
[1] 5.702093 1.105205 3.182726 2.992679 2.682283
rm(i, start_year, end_year, year_intervals, all_years, 
   wos_growth_rates, interval_growth_rates, WOS)

Table 1 - Taxonomy

identity_data <- experiments %>%
  select(contains("Identity")) %>%
  gather(value = "Identity")

class_data <- experiments %>%
  select(contains("Class")) %>%
  gather(value = "Class")

taxonomy <- data.frame(Class = class_data$Class, Identity = identity_data$Identity)

# Filter out rows with NA in the "Class" column (e.g., StressorTenClass is mostly NA)
taxonomy <- taxonomy %>%
  filter(!is.na(Class))

# Group by the "Class" column and summarize the unique identities
taxonomy_table <- taxonomy %>%
  group_by(Class, Identity) %>%
  summarize(Count = n()) %>%
  ### option to select by frequency of abundances ###
  #filter(Count >= 5) %>%
  group_by(Class) %>%
  ### where the magic happens ###
  summarize(Unique_Identities = paste0(Identity, " (", Count, ")", collapse = ", "), .groups = "drop")
`summarise()` has grouped output by 'Class'. You can override using the `.groups` argument.
# Reorder the rows based on the desired order for the taxonomy table
desired_order <- c("habitat alteration", "hydrology",  
                   "radiation", "sound", "temperature",
                   "UV light", "visible light", "water clarity",
                   
                   "microplastics", "nanoparticles", 
                   
                   "acidity", "alkalinity", "antibiotic", "carbon dioxide", 
                   "fungicide", "general biocide", "herbicide", "insecticide", 
                   "metals", "nutrients", 
                   "other chemicals", "oxygen", "pharmaceuticals", "salinity",
                   
                   "cyanotoxin",
                   
                   "biological alterations", "biological control", "disease",
                   "domestic species", "non-native species",
                   
                   "composite stressors")

taxonomy_table <- taxonomy_table[match(desired_order, taxonomy_table$Class), ]

# Create a nicely formatted table
#kable(taxonomy_table, format = "markdown", col.names = c("Class", "Unique Identities"))

# Taxonomy dataset to use for analyses 
taxonomy <- taxonomy %>%
  group_by(Class) %>%
  summarize(N = n()) %>%
  mutate(Nature = ifelse(Class %in% c("habitat alteration", "hydrology",  
                   "radiation", "sound", "temperature",
                   "UV light", "visible light", "water clarity"),
                   "Physical", 
                   ifelse(Class %in% c("biological alterations", 
                                       "biological control", "disease",
                                       "domestic species", "non-native species"),
                   "Biological",
                   ifelse(Class == "composite stressors", 
                          "Mixed", 
                        ifelse(Class == "cyanotoxin", "Biological-Chemical",
                               ifelse(Class %in% c("microplastics", "nanoparticles"), 
                                      "Chemical-Physical",
                                      "Chemical"))))))

Figure 2 - Stressor Classes

class_data <- experiments %>%
  select(c(Year, contains("Class"))) %>%
  pivot_longer(cols = contains("Class")) %>%
  drop_na() %>%
  select(-name) %>%
  mutate(Nature = ifelse(value %in% c("habitat alteration", "hydrology",  
                   "radiation", "sound", "temperature",
                   "UV light", "visible light", "water clarity"),
                   "Physical", 
                   ifelse(value %in% c("biological alterations", 
                                       "biological control", "disease",
                                       "domestic species", "non-native species"),
                   "Biological",
                   ifelse(value == "composite stressors", 
                          "Mixed", 
                        ifelse(value == "cyanotoxin", "Biological-Chemical",
                               ifelse(value %in% c("microplastics", "nanoparticles"), 
                                      "Chemical-Physical",
                                      "Chemical"))))))

### merge all years pre 1991 into 1990 (so that kernel density estimation is more accurate)
class_data <- class_data %>%
  mutate(Year = ifelse(Year < 1991, 1990, Year))


### summarise by Nature 
nature_data <- class_data %>%
  group_by(Year, Nature) %>%
  summarise(Count = n())
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
### summarise by Class 
class_data <- class_data %>%
  group_by(Year, value) %>%
  summarise(Count = n())
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
nature_data$Nature <- factor(nature_data$Nature, 
                            levels = c("Physical",
                                       "Chemical-Physical",
                                       "Chemical",
                                       "Biological-Chemical",
                                       "Biological",
                                       "Mixed"))

light.cols <- c("#FDF2CC", "#F1F2D2", "#E2F0D9", "#DDEAE7", "#DAE3F3", "#F2F2F2")
dark.cols <- c("#FCE699", "#E1E3A7", "#C5E0B4", "#BDD3CF", "#B4C7E7", "#E4E4E4")


ggplot(data = nature_data, 
       aes(x = Year,
           y = Count, 
           group = Nature, 
           fill = Nature)) +
  geom_stream(type = "proportion", bw = 0.65, n_grid = 1000,
              color = rgb(1, 1, 1), lwd = 0.2) +
  scale_fill_manual(values = dark.cols) +
  theme_minimal() +
  theme(panel.grid = element_blank()) +
  guides(fill = FALSE) +
  labs(y = "Proportion of Stressors")
Warning: The `<scale>` argument of `guides()` cannot be `FALSE`. Use "none" instead as of ggplot2 3.3.4.

rm(nature_data)
#first convert to proportions (as not using geom_stream anymore)
class_data <- class_data %>%
  group_by(Year) %>%
  mutate(proportion = Count / sum(Count))

Subset

class_data_sub <- class_data %>%
  filter(value %in% c("acidity", "habitat alteration", "metals",
                       "temperature", "UV light", "nanoparticles"))

class_data_sub$value <- factor(class_data_sub$value,
                               levels = desired_order)

ggplot(class_data_sub, 
       aes(x = Year,
           y = proportion)) +
  geom_smooth(method = "loess", span = 1,
              color = rgb(0.5, 0.5, 0.5), se = F) +
  geom_point(size = 0.5, alpha = 0.3) +
  theme_minimal() +
  labs(x = NULL, y = NULL) +
  theme(panel.background = element_rect(fill = "white", colour = "grey50")) +
  theme(panel.grid = element_blank()) +
  theme(axis.text.y = element_text(size = 4)) +
  facet_wrap(~value, scales = "free_y")  

NA
NA

All others (with 20+ occurrences)


class_data <- class_data %>%
  filter(!value %in% c("sound", "radiation", "domestic species", 
                       "biological control",
                       
                       "nanoparticles", "temperature", "UV light", 
                       "acidity", "habitat alteration", "metals"))

class_data$value <- factor(class_data$value, levels = desired_order)

ggplot(class_data, 
       aes(x = Year,
           y = proportion)) +
  geom_smooth(method = "loess", span = 1, 
              color = rgb(0.75, 0.75, 0.75), se = F) +
  geom_point(size = 0.5, alpha = 0.3) +
  theme_minimal() +
  labs(x = NULL, y = NULL) +
  theme(panel.background = element_rect(fill = "white", colour = "grey50")) +
  theme(panel.grid = element_blank()) +
  facet_wrap(~value, scales = "free_y", nrow =3, ncol =7)  


rm(class_data, class_data_sub)
combinations_sub <- combinations 

# Select class columns
class_network <- combinations_sub %>%
  select(contains("Class"))

# Get unique classes
unique_classes <- unique(unlist(class_network, use.names = FALSE), na.rm = TRUE)

# Initialize an empty co-occurrence matrix
co_occurrence_matrix <- matrix(0, nrow = length(unique_classes), ncol = length(unique_classes),
                                dimnames = list(unique_classes, unique_classes))

# Iterate through each row of the data frame
for (i in 1:nrow(class_network)) {
  # Get the classes in the current row
  row_classes <- na.omit(unlist(class_network[i, ]))
  
  # Increment co-occurrence counts for all pairs of classes in the row
  if (length(row_classes) > 1) {
    class_pairs <- combn(row_classes, 2)
    for (j in 1:ncol(class_pairs)) {
      class1 <- class_pairs[1, j]
      class2 <- class_pairs[2, j]
      co_occurrence_matrix[class1, class2] <- co_occurrence_matrix[class1, class2] + 1
      co_occurrence_matrix[class2, class1] <- co_occurrence_matrix[class2, class1] + 1
    }
  }
}

# Divide the diagonal cells by 2 (pairs of the same class have been counted twice)
diag(co_occurrence_matrix) <- diag(co_occurrence_matrix) / 2

# create full empty matrix with my desired order (based on nature of classes in the taxonomy)
full_matrix <- matrix(0, nrow = 31, ncol = 31)
colnames(full_matrix) <- rownames(full_matrix) <- desired_order

# Loop through the row and column names of the co_occurrence_matrix
for (row_name in rownames(co_occurrence_matrix)) {
  for (col_name in colnames(co_occurrence_matrix)) {
    # Check if the row and column names exist in the full_matrix
    if (row_name %in% rownames(full_matrix) && col_name %in% colnames(full_matrix)) {
      # Add the value from co_occurrence_matrix to the corresponding cell in full_matrix
      full_matrix[row_name, col_name] <- full_matrix[row_name, col_name] + co_occurrence_matrix[row_name, col_name]
    }
  }
}


##### Some manual checks to make sure everything is working as expected ######

### check rows with at least two of a class
#filtered_data <- class_network %>%
#  filter(rowSums(. == "salinity", na.rm = TRUE) >= 2)

### check rows with at least one of a class 
#filtered_data <- class_network %>%
#  rowwise() %>%
#  filter(any(c_across(everything()) == "radiation")) %>%
#  ungroup()

rm(class_pairs, class1, class2, i, j, row_classes, 
   class_network, co_occurrence_matrix)

co_occur_class <- full_matrix

Figure 3 - Stressor Identities

## filter identities (only if they occur five times)
identity_data <- experiments %>%
  select(contains("Identity")) %>%
  gather(value = "Identity")
class_data <- experiments %>%
  select(contains("Class")) %>%
  gather(value = "Class")
taxonomy <- data.frame(Class = class_data$Class, Identity = identity_data$Identity)
taxonomy <- taxonomy %>%
  group_by(Class,Identity) %>%
  summarize(Count = n()) %>%
  filter(Count >= 5) %>%
  drop_na() %>%
  mutate(Nature = ifelse(Class %in% c("habitat alteration", "hydrology",  
                   "radiation", "sound", "temperature",
                   "UV light", "visible light", "water clarity"),
                   "Physical", 
                   ifelse(Class %in% c("biological alterations", 
                                       "biological control", "disease",
                                       "domestic species", "non-native species"),
                   "Biological",
                   ifelse(Class == "composite stressors", 
                          "Mixed", 
                        ifelse(Class == "cyanotoxin", "Biological-Chemical",
                               ifelse(Class %in% c("microplastics", "nanoparticles"), 
                                      "Chemical-Physical",
                                      "Chemical")))))) %>%
  
  mutate(Colour = ifelse(Nature == "Physical", "#FCE699",
                         ifelse(Nature == "Chemical", "#C5E0B4", 
                                ifelse(Nature == "Biological", "#B4C7E7", 
                                       ifelse(Nature == "Mixed", "#c4c4c4",
                                              ifelse(Nature == "Biological-Chemical",
                                                     "#BDD3CF", "#E1E3A7")))))) %>%
  mutate(Labels = ifelse(Count >=15, Identity, ""))
`summarise()` has grouped output by 'Class'. You can override using the `.groups` argument.
  
combinations_sub <- combinations #%>%
  #filter(Year %in% c(1965:2021))

# Select class columns
identity_network <- combinations_sub %>%
  select(contains("Identity")) %>%
  mutate(across(everything(), ~ifelse(. %in% taxonomy$Identity, ., NA)))
  

# Get unique classes
unique_identities <- unique(unlist(identity_network, use.names = FALSE), na.rm = TRUE)

# Initialize an empty co-occurrence matrix
co_occurrence_matrix <- matrix(0, nrow = length(unique_identities), 
                               ncol = length(unique_identities),
                                dimnames = list(unique_identities, 
                                                unique_identities))

# Iterate through each row of the data frame
for (i in 1:nrow(identity_network)) {
  # Get the classes in the current row
  row_identities <- na.omit(unlist(identity_network[i, ]))
  
  # Increment co-occurrence counts for all pairs of classes in the row
  if (length(row_identities) > 1) {
    identity_pairs <- combn(row_identities, 2)
    for (j in 1:ncol(identity_pairs)) {
      identity1 <- identity_pairs[1, j]
      identity2 <- identity_pairs[2, j]
      co_occurrence_matrix[identity1, identity2] <- co_occurrence_matrix[identity1, identity2] + 1
      co_occurrence_matrix[identity2, identity1] <- co_occurrence_matrix[identity2, identity1] + 1
    }
  }
}

# Divide the diagonal cells by 2 (pairs of the same class have been counted twice)
diag(co_occurrence_matrix) <- diag(co_occurrence_matrix) / 2

rm(identity_pairs, identity1, identity2, i, j, 
   row_identities, identity_network, unique_identities)

# Get rid of the row that has a name that is NA
filtered_matrix <- co_occurrence_matrix[-2, -2]

LS0tCnRpdGxlOiAiRnJlc2h3YXRlciBNdWxpdC1TdHJlc3NvciBTeW50aGVzaXMgLSBGaWd1cmVzIgphdXRob3I6ICJKYW1lcyBPcnIiCm91dHB1dDoKICAgaHRtbF9ub3RlYm9vazoKICAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgICB0aGVtZTogZmxhdGx5CiAgICAgdG9jOiB0cnVlCiAgICAgdG9jX2RlcHRoOiA0CiAgICAgbnVtYmVyX3NlY3Rpb25zOiBubwotLS0KClRoaXMgUiBub3RlYm9vayBjb250YWlucyB0aGUgY29kZSB1c2VkIHRvIGNyZWF0ZSB0aGUgZmlndXJlcyBpbiB0aGUgcGFwZXI6ICJJbnRlcmFjdGlvbnMgYW1vbmcgYW50aHJvcG9nZW5pYyBzdHJlc3NvcnMgaW4gZnJlc2h3YXRlciBlY29zeXN0ZW1zOiBhIHN5c3RlbWF0aWMgcmV2aWV3IG9mIDIsMzk2IG11bHRpcGxlLXN0cmVzc29yIGV4cGVyaW1lbnRzIiBieSBKYW1lcyBBLiBPcnIsIFNhbXVlbCBKLiBNYWNhdWxheSwgQWRyaWFuYSBNb3JkZW50ZSwgQmVuamFtaW4gQnVyZ2VzcywgRGFuaWEgQWxiaW5pLCBKdWxpYSBHLiBIdW5uLCBLYXRoZXJpbiBSZXN0cmVwby1TdWxleiwgUmFtZXNoIFdpbHNvbiwgQW5uZSBTY2hlY2huZXIsIEFvaWZlIE0uIFJvYmVydHNvbiwgQmV0aGFueSBMZWUsIEJsYWtlIFN0dXBhcnlrLCBEZWxlemlhIFNpbmdoLCBJc29iZWwgT+KAmUxvdWdobGluLCBKZXJlbXkgSi4gUGlnZ290dCwgSmlhbmdxaXUgWmh1LCBLaHVvbmcgVi4gRGluaCwgTG91aXNlIEMuIEFyY2hlciwgTWFyY2luIFBlbmssIE1pbmggVGhpIFRodXkgVnUsIE5vw6tsIFAuRC4gSnV2aWdueS1La2VuYWZvdSwgUGVpeXUgWmhhbmcsIFBoaWxpcCBTYW5kZXJzLCBSYWxmIEIuIFNjaMOkZmVyLCBSb2xmIFZpbmVicm9va2UsIFNhYmluZSBIaWx0LCBUaG9tYXMgUmVlZCwgTWljaGVsbGUgQy4gSmFja3Nvbi4gCgojIyBTZXQtdXAKCi0gKlNldCB1cCBSIGVudmlvcm5tZW50KgoKYGBge3IsIHJlc3VsdHM9J2hpZGUnfQojIFIgdmVyc2lvbiA0LjMuMSAoMjAyMy0wNi0xNikKCnJtKGxpc3QgPSBscygpKSAgICAgICAgICAgIyBjbGVhciB0aGUgZW52aXJvbm1lbnQgCgojIFBhY2thZ2VzCmxpYnJhcnkoc2YpICAgICAgICAgICAgICAgIyBjbGFzc2VzIGFuZCBmdW5jdGlvbnMgZm9yIHZlY3RvciBkYXRhCmxpYnJhcnkocmFzdGVyKSAgICAgICAgICAgIyBjbGFzc2VzIGFuZCBmdW5jdGlvbnMgZm9yIHJhc3RlciBkYXRhCmxpYnJhcnkodGlkeXZlcnNlKSAgICAgICAgIyBvcmdhbmlzaW5nIGFuZCBtYW5pcHVsYXRpbmcgZGF0YQpsaWJyYXJ5KHNwRGF0YSkgICAgICAgICAgICMgZm9yIHdvcmxkIHNoYXBlZmlsZSAKbGlicmFyeShnZ1Zlbm5EaWFncmFtKSAgICAjIGZvciB2ZW5uIGRpYWdyYW0gZmlndXJlCmxpYnJhcnkoaWdyYXBoKSAgICAgICAgICAgIyB0byBjcmVhdGUgY28tb2NjdXJyZW5jZSBuZXR3b3JrIApsaWJyYXJ5KGtuaXRyKSAgICAgICAgICAgICMgdG8gY3JlYXRlIG5pY2UgdGFibGVzCmxpYnJhcnkocmVzaGFwZTIpICAgICAgICAgIyBmb3IgdGhlIG1lbHQgZnVuY3Rpb24gCmxpYnJhcnkobWFnaWNrKSAgICAgICAgICAgIyBmb3IgbWFraW5nIGdpZnMgCmxpYnJhcnkoZ2dzdHJlYW0pICAgICAgICAgIyBmb3IgcHJvcG9ydGlvbiBwbG90cwpsaWJyYXJ5KGdyaWRFeHRyYSkgICAgICAgICMgZm9yIGFycmFuZ2luZyBtdWx0aXBsZSBnZ3Bsb3RzCgpgYGAKCi0gKkxvYWQgZGF0YSoKClRoZSBgZXhwZXJpbWVudHNgIGRhdGFzZXQgY29udGFpbnMgMjM5NiByb3dzLCBvbmUgZm9yIGVhY2ggZXhwZXJpbWVudC4gVGhlIGBjb21iaW5hdGlvbnNgIGRhdGFzZXQgY29udGFpbnMgNDcxMiByb3dzLCBvbmUgZm9yIGVhY2ggY29tYmluYXRpb24gb2Ygc3RyZXNzb3JzLCB3aGljaCB3ZSB1c2UgZm9yIHRoZSBjby1vY2N1cnJlbmNlIGFuYWx5c2lzLiBUaGUgYFNwZWNpZmljQ29tYmluYXRpb25zYCBjb2x1bW4gaW4gdGhlIGBleHBlcmltZW50c2AgZGF0YXNldCBjb250YWlucyB0aGUgY29kaW5nIHVzZWQgdG8gY3JlYXRlIHRoZSBgY29tYmluYXRpb25zYC4gQSBkZXNjcmlwdGlvbiBvZiBhbGwgb2YgdGhlIGNvbHVtbnMgY2FuIGJlIGZvdW5kIGluIHRoZSBzdXBwb3J0aW5nIGluZm9ybWF0aW9uIG9mIHRoZSBwYXBlci4gCgpgYGB7cn0KZXhwZXJpbWVudHMgPC0gcmVhZC5jc3YoImRhdGEvZnJlc2h3YXRlcl9tdWx0aXN0cmVzc29yX2V4cGVyaW1lbnRzLmNzdiIsIGhlYWRlciA9IFQpCmNvbWJpbmF0aW9ucyA8LSByZWFkLmNzdigiZGF0YS9mcmVzaHdhdGVyX211bHRpc3RyZXNzb3JfY29tYmluYXRpb25zLmNzdiIsIGhlYWRlciA9IFQpCmBgYAoKIyMgRmlndXJlIDEgLSBPdmVydmlldwoKLSAqTWFwIG9mIGV4cGVyaW1lbnRzKgoKYGBge3IsIHJlc3VsdHMgPSAiaGlkZSJ9CiMgYWxsIGxvd2VyIGNhc2UgZmlyc3QKZXhwZXJpbWVudHMkQ291bnRyeSA8LSB0b2xvd2VyKGV4cGVyaW1lbnRzJENvdW50cnkpCgojIG9yZ2FuaXNlIGV4cGVyaW1lbnQgZGF0YQpjb3VudHJpZXMgPC0gZXhwZXJpbWVudHMgJT4lCiAgbXV0YXRlKGNvdW50cyA9IDEpICU+JQogIGdyb3VwX2J5KENvdW50cnkpICU+JQogIHN1bW1hcmlzZShleHBlcmltZW50cyA9IHN1bShjb3VudHMpKSAlPiUKICByZW5hbWUobmFtZV9sb25nID0gQ291bnRyeSkKCiMgTWVyY2F0b3IgLSBlcHNnOiAzODU3CiMgTW9sbHdlaWRlIC0gYHN0X2NycygnRVNSSTo1NDAwOScpYAojIFJvYmluc29uIC0gYHN0X2NycygnRVNSSTo1NDAzMCcpYAojIFdpbmtlbCBUcmlwbGUgLSBgc3RfY3JzKCdFU1JJOjU0MDE5JylgCgojIGxvYWQgY291bnRyeSBzaGFwZXMKd29ybGQgPC0gc3RfdHJhbnNmb3JtKHNwRGF0YTo6d29ybGQsIHN0X2NycygnRVNSSTo1NDAxOScpKSAKCiMgY2xlYW5pbmcgdG8gbWFrZSB0aGUgZGF0YWZyYW1lcyBjb25zaXN0ZW50CndvcmxkJG5hbWVfbG9uZyA8LSB0b2xvd2VyKHdvcmxkJG5hbWVfbG9uZykKY291bnRyaWVzJG5hbWVfbG9uZyA8LSB0b2xvd2VyKGNvdW50cmllcyRuYW1lX2xvbmcpCmNvdW50cmllcyRuYW1lX2xvbmcgPC1yZXBsYWNlKGNvdW50cmllcyRuYW1lX2xvbmcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cmllcyRuYW1lX2xvbmc9PSJydXNzaWEiLCAicnVzc2lhbiBmZWRlcmF0aW9uIikKY291bnRyaWVzJG5hbWVfbG9uZyA8LXJlcGxhY2UoY291bnRyaWVzJG5hbWVfbG9uZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnRyaWVzJG5hbWVfbG9uZz09InRoZSBuZXRoZXJsYW5kcyIsICJuZXRoZXJsYW5kcyIpCmNvdW50cmllcyRuYW1lX2xvbmcgPC1yZXBsYWNlKGNvdW50cmllcyRuYW1lX2xvbmcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cmllcyRuYW1lX2xvbmc9PSJ1ayIsICJ1bml0ZWQga2luZ2RvbSIpCmNvdW50cmllcyRuYW1lX2xvbmcgPC1yZXBsYWNlKGNvdW50cmllcyRuYW1lX2xvbmcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cmllcyRuYW1lX2xvbmc9PSJ1c2EiLCAidW5pdGVkIHN0YXRlcyIpCmNvdW50cmllcyRuYW1lX2xvbmcgPC1yZXBsYWNlKGNvdW50cmllcyRuYW1lX2xvbmcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cmllcyRuYW1lX2xvbmc9PSJzbG92YWsgcmVwdWJsaWMiLCAic2xvdmFraWEiKQoKIyBqb2luIGV4cGVyaW1lbnQgZGF0YSB0byBjb3VudHJpZXMgCndvcmxkIDwtIHdvcmxkICU+JQogIGxlZnRfam9pbihjb3VudHJpZXMsIGJ5ID0gIm5hbWVfbG9uZyIpICU+JQogIHNlbGVjdChuYW1lX2xvbmcsIGV4cGVyaW1lbnRzKQpgYGAKCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTZ9CgpnZ3Bsb3QoZGF0YSA9IHdvcmxkKSArCiAgCiAgZ2VvbV9zZihhZXMoZmlsbCA9IGV4cGVyaW1lbnRzKSwgY29sb3IgPSBOQSkgKwogIAogIGdlb21fc2YoZGF0YSA9IHN1YnNldCh3b3JsZCwgaXMubmEoZXhwZXJpbWVudHMpKSwgCiAgICAgICAgICBmaWxsID0gcmdiKDEsIDEsIDEpLCAKICAgICAgICAgIGNvbG9yID0gcmdiKDAuOCwgMC44LCAwLjgpKSArCiAgCiAgc2NhbGVfZmlsbF9ncmFkaWVudCh0cmFucyA9ICJzcXJ0IiwgCiAgICAgICAgICAgICAgICAgICAgICBsb3cgPSByZ2IoMC44LCAwLjgsIDAuOCksCiAgICAgICAgICAgICAgICAgICAgICBoaWdoID0gcmdiKDAuMiwgMC4yLCAwLjIpLAogICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYygxMCwgMTAwLCAyMDAsIDMwMCwgNDAwKSwKICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoMTAsIDEwMCwgMjAwLCAzMDAsIDQwMCkpICsKCiAgeGxhYigiIikgKyAKICAgIAogIHlsYWIoIiIpICsKICAKICBsYWJzKGZpbGwgPSAiZXhwZXJpbWVudHMiKSArCgogIHRoZW1lX21pbmltYWwoKSArCiAgCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuMTUsIDAuNCksICAjIEFkanVzdCBwb3NpdGlvbiBpbnNpZGUgdGhlIGdsb2JlCiAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3IgPSAiZ3JheSIpLAogICAgbGVnZW5kLmJveC5tYXJnaW4gPSBtYXJnaW4oNiwgNiwgNiwgNiksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoKQogICkKCnJtKGNvdW50cmllcywgd29ybGQpCmBgYAoKLSAqVmVubiBkaWFncmFtIG9mIHJlc3BvbnNlcyoKCmBgYHtyfQojIExpc3Qgb2YgaXRlbXMKeCA8LSBsaXN0KFBoeXNpb2xvZ2ljYWwgPSB3aGljaChleHBlcmltZW50cyRQaHlzaW9sb2dpY2FsID09ICJ5ZXMiKSwKICAgICAgICAgIEluZGl2aWR1YWwgPSB3aGljaChleHBlcmltZW50cyRJbmRpdmlkdWFsID09ICJ5ZXMiKSwgCiAgICAgICAgICBQb3B1bGF0aW9uID0gd2hpY2goZXhwZXJpbWVudHMkUG9wdWxhdGlvbiA9PSAieWVzIiksCiAgICAgICAgICBDb21tdW5pdHkgPSB3aGljaChleHBlcmltZW50cyRDb21tdW5pdHkgPT0gInllcyIpLAogICAgICAgICAgRWNvc3lzdGVtID0gd2hpY2goZXhwZXJpbWVudHMkRWNvc3lzdGVtID09ICJ5ZXMiKSkKCiMgVmVubiBkaWFncmFtCmdnVmVubkRpYWdyYW0oeCwgbGFiZWwgPSAiY291bnQiLCBsYWJlbF9hbHBoYSA9IDAsIGVkZ2Vfc2l6ZSA9IDAsCiAgICAgICAgICAgICAgbGFiZWxfc2l6ZSA9IDMsCiAgICAgICAgICAgICAgY2F0ZWdvcnkubmFtZXMgPSBjKCJQaHkuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkluZC4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUG9wLiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ29tLiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFY28uIikpICsKICAKICBsYWJzKGZpbGwgPSAiZXhwZXJpbWVudHMiKSArCiAgCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSByZ2IoMC44LCAwLjgsIDAuOCksIAogICAgICAgICAgICAgICAgICAgICAgaGlnaCA9IHJnYigwLjQsIDAuNCwgMC40KSwgdHJhbnMgPSAnc3FydCcpICsKICAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiZ3JleTMwIiwgImdyZXkzMCIsICJncmV5MzAiLCAiZ3JleTMwIiwgImdyZXkzMCIpKQogIApybSh4KQpgYGAKLSAqTnVtYmVyIG9mIFN0cmVzc29ycyBhbmQgRnVsbHkgRmFjdG9yaWFsKgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy53aWR0aD0zLjYsIGZpZy5oZWlnaHQ9My42fQpleHBlcmltZW50cyRTdHJlc3NvckNhdGVnb3J5IDwtIGlmZWxzZShleHBlcmltZW50cyROdW1iZXJPZlN0cmVzc29ycyA+IDEwLCAiPjEwIiwgYXMuY2hhcmFjdGVyKGV4cGVyaW1lbnRzJE51bWJlck9mU3RyZXNzb3JzKSkKZXhwZXJpbWVudHMkU3RyZXNzb3JDYXRlZ29yeSA8LSBmYWN0b3IoZXhwZXJpbWVudHMkU3RyZXNzb3JDYXRlZ29yeSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiMiIsICIzIiwgIjQiLCAiNSIsICI2IiwgIjciLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiOCIsICI5IiwgIjEwIiwgIj4xMCIpKQoKZ2dwbG90KGRhdGEgPSBleHBlcmltZW50cywgYWVzKHggPSBTdHJlc3NvckNhdGVnb3J5LCBmaWxsID0gRnVsbHlGYWN0b3JpYWwpKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAic3RhY2siKSArCiAgc2NhbGVfZmlsbF9tYW51YWwoYnJlYWtzID0gYygieWVzIiwgIm5vIiksCiAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygieWVzIiA9IHJnYigwLjQsIDAuNCwgMC40KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibm8iID0gcmdiKDAuOCwgMC44LCAwLjgpKSkgKwogIHhsYWIoIk51bWJlciBvZiBTdHJlc3NvcnMiKSArCiAgeWxhYigiRXhwZXJpbWVudHMiKSArCiAgbGFicyhmaWxsID0gIkZ1bGx5IGZhY3RvcmlhbCIpICsgICMgTGVnZW5kIGxhYmVsCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC43NSwgMC43NSksICAjIEFkanVzdCBwb3NpdGlvbiBhcyBuZWVkZWQKICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvciA9ICJncmF5IiksCiAgICBsZWdlbmQuYm94Lm1hcmdpbiA9IG1hcmdpbig2LCA2LCA2LCA2KSwKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksICAjIEFkanVzdCB4LWF4aXMgdGV4dCBzaXplCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheSIsIHNpemUgPSAwLjIpLCAgIyBDdXN0b21pemUgbWFqb3IgZ3JpZCBsaW5lcwogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpICAjIFJlbW92ZSBtaW5vciBncmlkIGxpbmVzCiAgKQoKYGBgCgotICpTdHJlc3NvciBMZXZlbHMqCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NH0KCiMgRmluZCB2YXJpYWJsZXMgY29udGFpbmluZyB0aGUgd29yZCAiTGV2ZWxzIgpsZXZlbHNfY29sdW1ucyA8LSBncmVwKCJMZXZlbHMiLCBuYW1lcyhleHBlcmltZW50cyksIHZhbHVlID0gVFJVRSkKCiMgRXh0cmFjdCB2YWx1ZXMgYW5kIGNvbWJpbmUgaW50byBhIHNpbmdsZSB2ZWN0b3IKY29tYmluZWRfbGV2ZWxzIDwtIHVubGlzdChleHBlcmltZW50c1tsZXZlbHNfY29sdW1uc10pCgojIENyZWF0ZSBhIGRhdGFmcmFtZSBmb3IgdGhlIGJhciBwbG90CmRhdGFfZm9yX2Jhcl9wbG90IDwtIGRhdGEuZnJhbWUoTGV2ZWxzID0gY29tYmluZWRfbGV2ZWxzKQoKIyBSZW1vdmUgTkFzIGFuZCB0dXJuIDFzIHRvIDJzCmRhdGFfZm9yX2Jhcl9wbG90IDwtIG5hLm9taXQoZGF0YV9mb3JfYmFyX3Bsb3QpCmRhdGFfZm9yX2Jhcl9wbG90JExldmVscyA8LSBpZmVsc2UoZGF0YV9mb3JfYmFyX3Bsb3QkTGV2ZWxzID09IDEsIDIsIGRhdGFfZm9yX2Jhcl9wbG90JExldmVscykKCiMgdHVybiB0byBjaGFyYWN0ZXIgYW5kIGFkZCBpbiA+MTAKZGF0YV9mb3JfYmFyX3Bsb3QkTGV2ZWxzIDwtIGlmZWxzZShkYXRhX2Zvcl9iYXJfcGxvdCRMZXZlbHMgPiAxMCwgIj4xMCIsIGFzLmNoYXJhY3RlcihkYXRhX2Zvcl9iYXJfcGxvdCRMZXZlbHMpKQpkYXRhX2Zvcl9iYXJfcGxvdCRMZXZlbHMgPC0gZmFjdG9yKGRhdGFfZm9yX2Jhcl9wbG90JExldmVscywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiMiIsICIzIiwgIjQiLCAiNSIsICI2IiwgIjciLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiOCIsICI5IiwgIjEwIiwgIj4xMCIpKQojIENyZWF0ZSB0aGUgYmFyIHBsb3QKZ2dwbG90KGRhdGEgPSBkYXRhX2Zvcl9iYXJfcGxvdCwgYWVzKHggPSBMZXZlbHMsICkpICsKICBnZW9tX2JhcihmaWxsID0gcmdiKDAuNCwgMC40LCAwLjQpKSArCiAgeGxhYigiTGV2ZWxzIikgKwogIHlsYWIoIlN0cmVzc29yIFRyZWF0bWVudHMiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksICAjIEFkanVzdCB4LWF4aXMgdGV4dCBzaXplCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheSIsIHNpemUgPSAwLjIpLCAgIyBDdXN0b21pemUgbWFqb3IgZ3JpZCBsaW5lcwogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpICAjIFJlbW92ZSBtaW5vciBncmlkIGxpbmVzCiAgKSAKcm0oZGF0YV9mb3JfYmFyX3Bsb3QsIGNvbWJpbmVkX2xldmVscywgbGV2ZWxzX2NvbHVtbnMpCgpgYGAKLSAqU3lzdGVtIGFuZCBIYWJpdGF0KgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTR9CgpleHBlcmltZW50cyRTeXN0ZW0gPC0gdG9sb3dlcihleHBlcmltZW50cyRTeXN0ZW0pCmV4cGVyaW1lbnRzJEhhYml0YXQgPC0gdG9sb3dlcihleHBlcmltZW50cyRIYWJpdGF0KQpleHBlcmltZW50cyRIYWJpdGF0W2lzLm5hKGV4cGVyaW1lbnRzJEhhYml0YXQpXSA8LSAiTkEiCgpleHBlcmltZW50cyRIYWJpdGF0IDwtIGZhY3RvcihleHBlcmltZW50cyRIYWJpdGF0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJOQSIsICJsZW50aWMiLCAibG90aWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIndldGxhbmQiLCAib3RoZXIiKSkKCgoKZ2dwbG90KGRhdGEgPSBleHBlcmltZW50cywgYWVzKHggPSByZW9yZGVyKFN5c3RlbSwgLXRhYmxlKFN5c3RlbSlbU3lzdGVtXSksIGZpbGwgPSBIYWJpdGF0KSkgKwogIGdlb21fYmFyKCkgKwogIHhsYWIoIlN5c3RlbSIpICsKICB5bGFiKCJFeHBlcmltZW50cyIpICsKICBsYWJzKGZpbGwgPSAiSGFiaXRhdCIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJOQSIgPSByZ2IoMC45LCAwLjksIDAuOSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImxlbnRpYyIgPSByZ2IoMC43LCAwLjcsIDAuNyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImxvdGljIiA9IHJnYigwLjUsIDAuNSwgMC41KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ3ZXRsYW5kIiA9IHJnYigwLjMsIDAuMywgMC4zKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJvdGhlciIgPSByZ2IoMC4xLCAwLjEsIDAuMSkpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44NSwgMC43MCksICAjIEFkanVzdCBwb3NpdGlvbiBhcyBuZWVkZWQKICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvciA9ICJncmF5IiksCiAgICBsZWdlbmQuYm94Lm1hcmdpbiA9IG1hcmdpbig2LCA2LCA2LCA2KSwKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksICAjIEFkanVzdCB4LWF4aXMgdGV4dCBzaXplCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheSIsIHNpemUgPSAwLjIpLCAgIyBDdXN0b21pemUgbWFqb3IgZ3JpZCBsaW5lcwogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpICAjIFJlbW92ZSBtaW5vciBncmlkIGxpbmVzCiAgKQpgYGAKCi0gKkR1cmF0aW9uKgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy53aWR0aD0zLjYsIGZpZy5oZWlnaHQ9My42fQpleHBlcmltZW50cyREdXJhdGlvbkRheXMgPC0gYXMubnVtZXJpYyhleHBlcmltZW50cyREdXJhdGlvbkRheXMpCmR1cmF0aW9uX2RhdGEgPC0gZXhwZXJpbWVudHNbIWlzLm5hKGV4cGVyaW1lbnRzJER1cmF0aW9uRGF5cyksIF0KCiMgRmlyc3QgbGV2ZWwgb2YgZ3JvdXBpbmcKYmlucyA8LSBjKDAsIDMwLCA2MCwgOTAsIDEyMCwgMTUwLCAxODAsIDM2NSwgSW5mKQpiaW5fbGFiZWxzIDwtIGMoIjAtMzAiLCAiMzAtNjAiLCAiNjAtOTAiLCAiOTAtMTIwIiwgIjEyMC0xNTAiLCAiMTUwLTE4MCIsICIxODAtMzY1IiwgIj4zNjUiKQpkdXJhdGlvbl9kYXRhJER1cmF0aW9uQmluIDwtIGN1dChkdXJhdGlvbl9kYXRhJER1cmF0aW9uRGF5cywgYnJlYWtzID0gYmlucywgbGFiZWxzID0gYmluX2xhYmVscykKCiMgU2Vjb25kIGxldmVsIG9mIGdyb3VwaW5nCmJpbnMgPC0gYygwLCAxLCAyLCA0LCA3LCAxNCwgMzAsIEluZikKYmluX2xhYmVscyA8LSBjKCIwLTEiLCAiMS0yIiwgIjItNCIsICI0LTciLCAiNy0xNCIsICIxNC0zMCIsICI+MzAiKQpkdXJhdGlvbl9kYXRhJER1cmF0aW9uQmluMiA8LSBjdXQoZHVyYXRpb25fZGF0YSREdXJhdGlvbkRheXMsIGJyZWFrcyA9IGJpbnMsIGxhYmVscyA9IGJpbl9sYWJlbHMpCgpibHVlX3BhbGV0dGUgPC0gY29sb3JSYW1wUGFsZXR0ZShjKHJnYigwLjksIDAuOSwgMC45KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmdiKDAuMSwgMC4xLCAwLjEpKSkoNykKCgojIFBsb3QKZ2dwbG90KGRhdGEgPSBkdXJhdGlvbl9kYXRhLCBhZXMoeCA9IER1cmF0aW9uQmluLCBmaWxsID0gRHVyYXRpb25CaW4yKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gInN0YWNrIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIjAtMSIgPSBibHVlX3BhbGV0dGVbMV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMS0yIj0gYmx1ZV9wYWxldHRlWzJdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyLTQiPSBibHVlX3BhbGV0dGVbM10sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjQtNyI9IGJsdWVfcGFsZXR0ZVs0XSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiNy0xNCI9IGJsdWVfcGFsZXR0ZVs1XSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMTQtMzAiPSBibHVlX3BhbGV0dGVbNl0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIj4zMCI9IGJsdWVfcGFsZXR0ZVs3XSkpICsKICB4bGFiKCJEYXlzIikgKwogIHlsYWIoIkV4cGVyaW1lbnRzIikgKwogIGxhYnMoZmlsbCA9ICJEYXlzIikgKyAgIyBMZWdlbmQgbGFiZWwKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjc1LCAwLjY1KSwgICMgQWRqdXN0IHBvc2l0aW9uIGFzIG5lZWRlZAogICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gImdyYXkiKSwKICAgIGxlZ2VuZC5ib3gubWFyZ2luID0gbWFyZ2luKDYsIDYsIDYsIDYpLAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcsIGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksICAjIEFkanVzdCB4LWF4aXMgdGV4dCBzaXplCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheSIsIHNpemUgPSAwLjIpLCAgIyBDdXN0b21pemUgbWFqb3IgZ3JpZCBsaW5lcwogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpICAjIFJlbW92ZSBtaW5vciBncmlkIGxpbmVzCiAgKSAKCnJtKGR1cmF0aW9uX2RhdGEsIGJsdWVfcGFsZXR0ZSwgYmlucywgYmluX2xhYmVscykKYGBgCgotICpUYXhvbm9taWMgR3JvdXBzKgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy53aWR0aD0zLjYsIGZpZy5oZWlnaHQ9NH0KZXhwZXJpbWVudHMkVGF4b25vbWljR3JvdXAgPC0gdG9sb3dlcihleHBlcmltZW50cyRUYXhvbm9taWNHcm91cCkKZXhwZXJpbWVudHMkVGF4b25vbWljR3JvdXAgPC0gc3ViKCJ0ZXJyZXN0cmlhbCBwbGFudHMiLCAib3RoZXIgcGxhbnRzIiwgZXhwZXJpbWVudHMkVGF4b25vbWljR3JvdXApCgp0YXhhIDwtIGV4cGVyaW1lbnRzCgp0YXhhJFRheG9ub21pY0dyb3VwW2lzLm5hKHRheGEkVGF4b25vbWljR3JvdXApXSA8LSAiY29tbXVuaXRpZXMiCgojIHJlbW92ZSBncm91cHMgZnJvbSB0aGUgcGxvdCB0aGF0IG9jY3VyIGxlc3MgdGhhbiA1IHRpbWVzCnRheGEgPC0gdGF4YSAlPiUKICBtdXRhdGUoc2luZ2xlID0gaWZlbHNlKFRheG9ub21pY0dyb3VwID09ICJjb21tdW5pdGllcyIsICJubyIsICJ5ZXMiKSkgJT4lCiAgZ3JvdXBfYnkoVGF4b25vbWljR3JvdXApICU+JQogIGZpbHRlcihuKCkgPj0gNSkgJT4lCiAgdW5ncm91cCgpCgpnZ3Bsb3QoZGF0YSA9IHRheGEsIGFlcyh4ID0gcmVvcmRlcihUYXhvbm9taWNHcm91cCwgLXRhYmxlKFRheG9ub21pY0dyb3VwKVtUYXhvbm9taWNHcm91cF0pLAogICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gc2luZ2xlKSkgKwogIGdlb21fYmFyKCkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKGJyZWFrcyA9IGMoInllcyIsICJubyIpLAogICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGMoInllcyIgPSByZ2IoMC40LCAwLjQsIDAuNCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5vIiA9IHJnYigwLjgsIDAuOCwgMC44KSkpICsKICB4bGFiKCIiKSArCiAgeWxhYigiRXhwZXJpbWVudHMiKSArCiAgbGFicyhmaWxsID0gIlNpbmdsZSBTcGVjaWVzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuOCwgMC44MCksICAjIEFkanVzdCBwb3NpdGlvbiBhcyBuZWVkZWQKICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvciA9ICJncmF5IiksCiAgICBsZWdlbmQuYm94Lm1hcmdpbiA9IG1hcmdpbig2LCA2LCA2LCA2KSwKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwgICMgQWRqdXN0IHgtYXhpcyB0ZXh0IHNpemUKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmF5Iiwgc2l6ZSA9IDAuMiksICAjIEN1c3RvbWl6ZSBtYWpvciBncmlkIGxpbmVzCiAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCkgICMgUmVtb3ZlIG1pbm9yIGdyaWQgbGluZXMKICApCgpybSh0YXhhKQpgYGAKLSAqVGVtcG9yYWwgQXNwZWN0cyoKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcud2lkdGg9Ny4yLCBmaWcuaGVpZ2h0PTR9CmV4cGVyaW1lbnRzJFNlcXVlbnRpYWwgPC0gdG9sb3dlcihleHBlcmltZW50cyRTZXF1ZW50aWFsKQpleHBlcmltZW50cyRNdWx0aXBsZVRpbWVwb2ludHMgPC0gdG9sb3dlcihleHBlcmltZW50cyRNdWx0aXBsZVRpbWVwb2ludHMpCmV4cGVyaW1lbnRzJFJlY292ZXJ5IDwtIHRvbG93ZXIoZXhwZXJpbWVudHMkUmVjb3ZlcnkpCgpwMSA8LSBnZ3Bsb3QoZGF0YSA9IGV4cGVyaW1lbnRzLCBhZXMoeCA9IE11bHRpcGxlVGltZXBvaW50cykpICsKICBnZW9tX2JhcihmaWxsID0gcmdiKDAuNSwgMC41LCAwLjUpKSArCiAgZ2d0aXRsZSgiTXVsdGlwbGUgVGltZXBvaW50cyIpICsKICB4bGFiKCIiKSArCiAgeWxhYigiRXhwZXJpbWVudHMiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0PTAuNSksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbihyID0gMjApKSkgKwogIHlsaW0oMCwgMjI1MCkKCnAyIDwtIGdncGxvdChkYXRhID0gZXhwZXJpbWVudHMsIGFlcyh4ID0gU2VxdWVudGlhbCkpICsKICBnZW9tX2JhcihmaWxsID0gcmdiKDAuNSwgMC41LCAwLjUpKSArCiAgZ2d0aXRsZSgiU2VxdWVudGlhbCIpICsKICB4bGFiKCIiKSArCiAgeWxhYigiIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdD0wLjUpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4ociA9IDIwKSkpICsKICB5bGltKDAsIDIyNTApCgpwMyA8LSBnZ3Bsb3QoZGF0YSA9IGV4cGVyaW1lbnRzLCBhZXMoeCA9IFJlY292ZXJ5KSwpICsKICBnZW9tX2JhcihmaWxsID0gcmdiKDAuNSwgMC41LCAwLjUpKSArCiAgZ2d0aXRsZSgiUmVjb3ZlcnkiKSArCiAgeGxhYigiIikgKwogIHlsYWIoIiIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3Q9MC41KSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHIgPSAyMCkpKSArCiAgeWxpbSgwLCAyMjUwKQoKZ3JpZC5hcnJhbmdlKHAxLCBwMiwgcDMsIG5jb2wgPSAzKQpybShwMSwgcDIsIHAzKQpgYGAKLSAqUHVibGljYXRpb24gZ3Jvd3RoIHJhdGUqCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLndpZHRoPTExLCBmaWcuaGVpZ2h0PTR9CgpleHBlcmltZW50cyRTeXN0ZW0gPC0gZmFjdG9yKGV4cGVyaW1lbnRzJFN5c3RlbSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygibGFiIiwgIm1lc29jb3NtIiwgImZpZWxkIikpCgpibHVlX3BhbGV0dGUgPC0gY29sb3JSYW1wUGFsZXR0ZShjKHJnYigwLjcsIDAuNywgMC43KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmdiKDAuNCwgMC40LCAwLjQpKSkoMykKCmdncGxvdChkYXRhID0gc3Vic2V0KGV4cGVyaW1lbnRzLCAhaXMubmEoU3lzdGVtKSksIAogICAgICAgYWVzKHggPSBZZWFyLCBmaWxsID0gU3lzdGVtKSkgKwogIGdlb21fYmFyKCkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImxhYiIgPSBibHVlX3BhbGV0dGVbMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1lc29jb3NtIiA9IGJsdWVfcGFsZXR0ZVsyXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmaWVsZCIgPSBibHVlX3BhbGV0dGVbM10pKSArCiAgeGxhYigiWWVhciIpICsKICB5bGFiKCJFeHBlcmltZW50cyIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihleHBlcmltZW50cyRZZWFyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgoZXhwZXJpbWVudHMkWWVhciksIGJ5ID0gNSkpICsgIAogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuNywgMC44MCksICAjIEFkanVzdCBwb3NpdGlvbiBhcyBuZWVkZWQKICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvciA9ICJncmF5IiksCiAgICBsZWdlbmQuYm94Lm1hcmdpbiA9IG1hcmdpbig2LCA2LCA2LCA2KSwKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksICAjIEFkanVzdCB4LWF4aXMgdGV4dCBzaXplCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheSIsIHNpemUgPSAwLjIpLCAgIyBDdXN0b21pemUgbWFqb3IgZ3JpZCBsaW5lcwogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpICAjIFJlbW92ZSBtaW5vciBncmlkIGxpbmVzCiAgKQoKYGBgCgotICpDb21wYXJlZCB0byAiQmlvbG9neSIgaW4gV09TKgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy53aWR0aD0zLCBmaWcuaGVpZ2h0PTEuNX0KCldPUyA8LSByZWFkLmNzdigiZGF0YS9XT1MtQmlvbG9neS5jc3YiLCBoZWFkZXIgPSBUKQoKZXhwZXJpbWVudHNfeWVhciA8LSBleHBlcmltZW50cyAlPiUKICBncm91cF9ieShZZWFyKSAlPiUKICBzdW1tYXJpemUoZXhwZXJpbWVudHMgPSBuKCkpICU+JQogIHVuZ3JvdXAoKQoKIyBDcmVhdGUgYSBzZXF1ZW5jZSBvZiB5ZWFycyBmcm9tIDE5NjUgdG8gMjAyMgphbGxfeWVhcnMgPC0gc2VxKDE5NjUsIDIwMjEpCgojIFVzZSB0aGUgY29tcGxldGUoKSBmdW5jdGlvbiB0byBmaWxsIGluIG1pc3NpbmcgeWVhcnMgd2l0aCAwIGV4cGVyaW1lbnRzCmV4cGVyaW1lbnRzX3llYXIgPC0gZXhwZXJpbWVudHNfeWVhciAlPiUKICBjb21wbGV0ZShZZWFyID0gYWxsX3llYXJzLCBmaWxsID0gbGlzdChleHBlcmltZW50cyA9IDApKSAlPiUKICBsZWZ0X2pvaW4oV09TKQoKCmBgYAoKYGBge3J9CiMgRGVmaW5lIHRoZSB5ZWFyIGludGVydmFscwp5ZWFyX2ludGVydmFscyA8LSBjKDE5NzAsIDE5ODAsIDE5OTAsIDIwMDAsIDIwMTAsIDIwMjApCgojIENhbGN1bGF0ZSBhbm51YWwgZ3Jvd3RoIHJhdGVzIGZvciBleHBlcmltZW50cyBhbmQgV09TLkJpb2xvZ3kgd2l0aGluIGVhY2ggaW50ZXJ2YWwKYW5udWFsX2dyb3d0aF9yYXRlcyA8LSBkYXRhLmZyYW1lKCkKCmZvciAoaSBpbiAxOihsZW5ndGgoeWVhcl9pbnRlcnZhbHMpIC0gMSkpIHsKICBzdGFydF95ZWFyIDwtIHllYXJfaW50ZXJ2YWxzW2ldCiAgZW5kX3llYXIgPC0geWVhcl9pbnRlcnZhbHNbaSArIDFdCiAgCiAgaW50ZXJ2YWxfZ3Jvd3RoX3JhdGVzIDwtIGV4cGVyaW1lbnRzX3llYXIgJT4lCiAgICBmaWx0ZXIoWWVhciA+PSBzdGFydF95ZWFyLCBZZWFyIDwgZW5kX3llYXIpICU+JQogICAgc3VtbWFyaXNlKGV4cGVyaW1lbnRzX2dyb3d0aCA9ICgoKGxhc3QoZXhwZXJpbWVudHMpL2ZpcnN0KGV4cGVyaW1lbnRzKSleKDEvMTApKSAtIDEpICogMTAwLAogICAgICAgICAgICAgIHdvc19ncm93dGggPSAoKChsYXN0KFdPUy5CaW9sb2d5KS9maXJzdChXT1MuQmlvbG9neSkpXigxLzEwKSkgLSAxKSAqIDEwMCkKICAKICBhbm51YWxfZ3Jvd3RoX3JhdGVzIDwtIGJpbmRfcm93cyhhbm51YWxfZ3Jvd3RoX3JhdGVzLCBpbnRlcnZhbF9ncm93dGhfcmF0ZXMpCn0KCiMgRXh0cmFjdCBhbmQgcmV0dXJuIHRoZSBhbm51YWwgZ3Jvd3RoIHJhdGVzIGFzIHZlY3RvcnMKZXhwZXJpbWVudHNfZ3Jvd3RoX3JhdGVzIDwtIGFubnVhbF9ncm93dGhfcmF0ZXMkZXhwZXJpbWVudHNfZ3Jvd3RoCndvc19ncm93dGhfcmF0ZXMgPC0gYW5udWFsX2dyb3d0aF9yYXRlcyR3b3NfZ3Jvd3RoCgpleHBlcmltZW50c19ncm93dGhfcmF0ZXMKd29zX2dyb3d0aF9yYXRlcwoKcm0oaSwgc3RhcnRfeWVhciwgZW5kX3llYXIsIHllYXJfaW50ZXJ2YWxzLCBhbGxfeWVhcnMsIAogICB3b3NfZ3Jvd3RoX3JhdGVzLCBpbnRlcnZhbF9ncm93dGhfcmF0ZXMsIFdPUykKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9NCwgZHBpID0gMzAwfQoKcGFyKG1hciA9IGMoNSwgNCwgNSwgNykpICAjIEFkanVzdCB0aGUgcmlnaHQgbWFyZ2luIHRvIG1ha2Ugc3BhY2UgZm9yIHRoZSBzZWNvbmQgeS1heGlzIGxhYmVsCgpwbG90KGV4cGVyaW1lbnRzX3llYXIkWWVhciwgZXhwZXJpbWVudHNfeWVhciRXT1MuQmlvbG9neSAvIDEwMDAsCiAgICAgdHlwZSA9ICJuIiwgeGxhYiA9ICIiLCAKICAgICB5bGFiID0gIldvUyAodGhvdXNhbmRzKSIsIAogICAgIGxhcyA9IDEsIAogICAgIHlsaW0gPSBjKDIwLCAyNTApKQoKYWJsaW5lKHYgPSBjKDE5NzAsIDE5ODAsIDE5OTAsIDIwMDAsIDIwMTAsIDIwMjApLAogICAgICAgY29sID0gcmdiKDAuOSwgMC45LCAwLjkpLCBsd2QgPSAyLjUpCgpwb2ludHMoZXhwZXJpbWVudHNfeWVhciRZZWFyLCBleHBlcmltZW50c195ZWFyJFdPUy5CaW9sb2d5IC8gMTAwMCwgCiAgICAgICBjb2wgPSByZ2IoMC4yLCAwLjIsIDAuMiksIAogICAgICAgcGNoID0gMTYsIGNleCA9IDAuOSkgICMgU29saWQgY2lyY2xlIHBvaW50cwoKcGFyKG5ldyA9IFRSVUUpCnBsb3QoZXhwZXJpbWVudHNfeWVhciRZZWFyLCBleHBlcmltZW50c195ZWFyJGV4cGVyaW1lbnRzIC8gMTUwLAogICAgIHR5cGUgPSAibiIsIHhsYWIgPSAiIiwgeWxhYiA9ICIiLCB5bGltID0gYygwLCAyKSwgYXhlcyA9IEZBTFNFLAogICAgIHlheHQgPSAibiIsIGNvbC5heGlzID0gcmdiKDAuNSwgMC41LCAwLjUpKSAgIyBTZXQgeS1heGlzIGNvbG9yIHRvIGdyZXkKCnBvaW50cyhleHBlcmltZW50c195ZWFyJFllYXIsIGV4cGVyaW1lbnRzX3llYXIkZXhwZXJpbWVudHMgLyAxNTAsIAogICAgICAgY29sID0gcmdiKDAuNSwgMC41LCAwLjUpLCBwY2ggPSAxLCBjZXggPSAwLjkpICAjIFNvbGlkIGNpcmNsZSBwb2ludHMKCm10ZXh0KCJFeHBlcmltZW50cyIsIHNpZGUgPSA0LCBsaW5lID0gMywgY29sID0gcmdiKDAuNSwgMC41LCAwLjUpKQoKYXhpcyg0LCBhdCA9IHNlcSgwLCAzMDAgLyAxNTAsIGJ5ID0gNjAgLyAxNTApLCAKICAgICBsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKHNlcSgwLCAzMDAsIGJ5ID0gNjApKSwKICAgICBsYXMgPSAxLCBjb2wuYXhpcyA9IHJnYigwLjUsIDAuNSwgMC41KSkgICMgU2V0IHktYXhpcyBjb2xvciB0byBncmV5CgpybShleHBlcmltZW50c195ZWFyLCBhbm51YWxfZ3Jvd3RoX3JhdGVzLCBleHBlcmltZW50c19ncm93dGhfcmF0ZXMpCmBgYAoKIyMgVGFibGUgMSAtIFRheG9ub215CgpgYGB7cn0KaWRlbnRpdHlfZGF0YSA8LSBleHBlcmltZW50cyAlPiUKICBzZWxlY3QoY29udGFpbnMoIklkZW50aXR5IikpICU+JQogIGdhdGhlcih2YWx1ZSA9ICJJZGVudGl0eSIpCgpjbGFzc19kYXRhIDwtIGV4cGVyaW1lbnRzICU+JQogIHNlbGVjdChjb250YWlucygiQ2xhc3MiKSkgJT4lCiAgZ2F0aGVyKHZhbHVlID0gIkNsYXNzIikKCnRheG9ub215IDwtIGRhdGEuZnJhbWUoQ2xhc3MgPSBjbGFzc19kYXRhJENsYXNzLCBJZGVudGl0eSA9IGlkZW50aXR5X2RhdGEkSWRlbnRpdHkpCgojIEZpbHRlciBvdXQgcm93cyB3aXRoIE5BIGluIHRoZSAiQ2xhc3MiIGNvbHVtbiAoZS5nLiwgU3RyZXNzb3JUZW5DbGFzcyBpcyBtb3N0bHkgTkEpCnRheG9ub215IDwtIHRheG9ub215ICU+JQogIGZpbHRlcighaXMubmEoQ2xhc3MpKQoKIyBHcm91cCBieSB0aGUgIkNsYXNzIiBjb2x1bW4gYW5kIHN1bW1hcml6ZSB0aGUgdW5pcXVlIGlkZW50aXRpZXMKdGF4b25vbXlfdGFibGUgPC0gdGF4b25vbXkgJT4lCiAgZ3JvdXBfYnkoQ2xhc3MsIElkZW50aXR5KSAlPiUKICBzdW1tYXJpemUoQ291bnQgPSBuKCkpICU+JQogICMjIyBvcHRpb24gdG8gc2VsZWN0IGJ5IGZyZXF1ZW5jeSBvZiBhYnVuZGFuY2VzICMjIwogICNmaWx0ZXIoQ291bnQgPj0gNSkgJT4lCiAgZ3JvdXBfYnkoQ2xhc3MpICU+JQogICMjIyB3aGVyZSB0aGUgbWFnaWMgaGFwcGVucyAjIyMKICBzdW1tYXJpemUoVW5pcXVlX0lkZW50aXRpZXMgPSBwYXN0ZTAoSWRlbnRpdHksICIgKCIsIENvdW50LCAiKSIsIGNvbGxhcHNlID0gIiwgIiksIC5ncm91cHMgPSAiZHJvcCIpCgoKIyBSZW9yZGVyIHRoZSByb3dzIGJhc2VkIG9uIHRoZSBkZXNpcmVkIG9yZGVyIGZvciB0aGUgdGF4b25vbXkgdGFibGUKZGVzaXJlZF9vcmRlciA8LSBjKCJoYWJpdGF0IGFsdGVyYXRpb24iLCAiaHlkcm9sb2d5IiwgIAogICAgICAgICAgICAgICAgICAgInJhZGlhdGlvbiIsICJzb3VuZCIsICJ0ZW1wZXJhdHVyZSIsCiAgICAgICAgICAgICAgICAgICAiVVYgbGlnaHQiLCAidmlzaWJsZSBsaWdodCIsICJ3YXRlciBjbGFyaXR5IiwKICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIm1pY3JvcGxhc3RpY3MiLCAibmFub3BhcnRpY2xlcyIsIAogICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAiYWNpZGl0eSIsICJhbGthbGluaXR5IiwgImFudGliaW90aWMiLCAiY2FyYm9uIGRpb3hpZGUiLCAKICAgICAgICAgICAgICAgICAgICJmdW5naWNpZGUiLCAiZ2VuZXJhbCBiaW9jaWRlIiwgImhlcmJpY2lkZSIsICJpbnNlY3RpY2lkZSIsIAogICAgICAgICAgICAgICAgICAgIm1ldGFscyIsICJudXRyaWVudHMiLCAKICAgICAgICAgICAgICAgICAgICJvdGhlciBjaGVtaWNhbHMiLCAib3h5Z2VuIiwgInBoYXJtYWNldXRpY2FscyIsICJzYWxpbml0eSIsCiAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICJjeWFub3RveGluIiwKICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgImJpb2xvZ2ljYWwgYWx0ZXJhdGlvbnMiLCAiYmlvbG9naWNhbCBjb250cm9sIiwgImRpc2Vhc2UiLAogICAgICAgICAgICAgICAgICAgImRvbWVzdGljIHNwZWNpZXMiLCAibm9uLW5hdGl2ZSBzcGVjaWVzIiwKICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgImNvbXBvc2l0ZSBzdHJlc3NvcnMiKQoKdGF4b25vbXlfdGFibGUgPC0gdGF4b25vbXlfdGFibGVbbWF0Y2goZGVzaXJlZF9vcmRlciwgdGF4b25vbXlfdGFibGUkQ2xhc3MpLCBdCgojIENyZWF0ZSBhIG5pY2VseSBmb3JtYXR0ZWQgdGFibGUKI2thYmxlKHRheG9ub215X3RhYmxlLCBmb3JtYXQgPSAibWFya2Rvd24iLCBjb2wubmFtZXMgPSBjKCJDbGFzcyIsICJVbmlxdWUgSWRlbnRpdGllcyIpKQoKIyBUYXhvbm9teSBkYXRhc2V0IHRvIHVzZSBmb3IgYW5hbHlzZXMgCnRheG9ub215IDwtIHRheG9ub215ICU+JQogIGdyb3VwX2J5KENsYXNzKSAlPiUKICBzdW1tYXJpemUoTiA9IG4oKSkgJT4lCiAgbXV0YXRlKE5hdHVyZSA9IGlmZWxzZShDbGFzcyAlaW4lIGMoImhhYml0YXQgYWx0ZXJhdGlvbiIsICJoeWRyb2xvZ3kiLCAgCiAgICAgICAgICAgICAgICAgICAicmFkaWF0aW9uIiwgInNvdW5kIiwgInRlbXBlcmF0dXJlIiwKICAgICAgICAgICAgICAgICAgICJVViBsaWdodCIsICJ2aXNpYmxlIGxpZ2h0IiwgIndhdGVyIGNsYXJpdHkiKSwKICAgICAgICAgICAgICAgICAgICJQaHlzaWNhbCIsIAogICAgICAgICAgICAgICAgICAgaWZlbHNlKENsYXNzICVpbiUgYygiYmlvbG9naWNhbCBhbHRlcmF0aW9ucyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYmlvbG9naWNhbCBjb250cm9sIiwgImRpc2Vhc2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZG9tZXN0aWMgc3BlY2llcyIsICJub24tbmF0aXZlIHNwZWNpZXMiKSwKICAgICAgICAgICAgICAgICAgICJCaW9sb2dpY2FsIiwKICAgICAgICAgICAgICAgICAgIGlmZWxzZShDbGFzcyA9PSAiY29tcG9zaXRlIHN0cmVzc29ycyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICJNaXhlZCIsIAogICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoQ2xhc3MgPT0gImN5YW5vdG94aW4iLCAiQmlvbG9naWNhbC1DaGVtaWNhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoQ2xhc3MgJWluJSBjKCJtaWNyb3BsYXN0aWNzIiwgIm5hbm9wYXJ0aWNsZXMiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNoZW1pY2FsLVBoeXNpY2FsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2hlbWljYWwiKSkpKSkpCgpgYGAKCiMjIEZpZ3VyZSAyIC0gU3RyZXNzb3IgQ2xhc3NlcwoKLSAqU3RyZXNzb3IgbmF0dXJlcyBvdmVyIHRpbWUqCgpgYGB7cn0KY2xhc3NfZGF0YSA8LSBleHBlcmltZW50cyAlPiUKICBzZWxlY3QoYyhZZWFyLCBjb250YWlucygiQ2xhc3MiKSkpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gY29udGFpbnMoIkNsYXNzIikpICU+JQogIGRyb3BfbmEoKSAlPiUKICBzZWxlY3QoLW5hbWUpICU+JQogIG11dGF0ZShOYXR1cmUgPSBpZmVsc2UodmFsdWUgJWluJSBjKCJoYWJpdGF0IGFsdGVyYXRpb24iLCAiaHlkcm9sb2d5IiwgIAogICAgICAgICAgICAgICAgICAgInJhZGlhdGlvbiIsICJzb3VuZCIsICJ0ZW1wZXJhdHVyZSIsCiAgICAgICAgICAgICAgICAgICAiVVYgbGlnaHQiLCAidmlzaWJsZSBsaWdodCIsICJ3YXRlciBjbGFyaXR5IiksCiAgICAgICAgICAgICAgICAgICAiUGh5c2ljYWwiLCAKICAgICAgICAgICAgICAgICAgIGlmZWxzZSh2YWx1ZSAlaW4lIGMoImJpb2xvZ2ljYWwgYWx0ZXJhdGlvbnMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJpb2xvZ2ljYWwgY29udHJvbCIsICJkaXNlYXNlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImRvbWVzdGljIHNwZWNpZXMiLCAibm9uLW5hdGl2ZSBzcGVjaWVzIiksCiAgICAgICAgICAgICAgICAgICAiQmlvbG9naWNhbCIsCiAgICAgICAgICAgICAgICAgICBpZmVsc2UodmFsdWUgPT0gImNvbXBvc2l0ZSBzdHJlc3NvcnMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAiTWl4ZWQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHZhbHVlID09ICJjeWFub3RveGluIiwgIkJpb2xvZ2ljYWwtQ2hlbWljYWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHZhbHVlICVpbiUgYygibWljcm9wbGFzdGljcyIsICJuYW5vcGFydGljbGVzIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDaGVtaWNhbC1QaHlzaWNhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNoZW1pY2FsIikpKSkpKQoKIyMjIG1lcmdlIGFsbCB5ZWFycyBwcmUgMTk5MSBpbnRvIDE5OTAgKHNvIHRoYXQga2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbiBpcyBtb3JlIGFjY3VyYXRlKQpjbGFzc19kYXRhIDwtIGNsYXNzX2RhdGEgJT4lCiAgbXV0YXRlKFllYXIgPSBpZmVsc2UoWWVhciA8IDE5OTEsIDE5OTAsIFllYXIpKQoKCiMjIyBzdW1tYXJpc2UgYnkgTmF0dXJlIApuYXR1cmVfZGF0YSA8LSBjbGFzc19kYXRhICU+JQogIGdyb3VwX2J5KFllYXIsIE5hdHVyZSkgJT4lCiAgc3VtbWFyaXNlKENvdW50ID0gbigpKQoKIyMjIHN1bW1hcmlzZSBieSBDbGFzcyAKY2xhc3NfZGF0YSA8LSBjbGFzc19kYXRhICU+JQogIGdyb3VwX2J5KFllYXIsIHZhbHVlKSAlPiUKICBzdW1tYXJpc2UoQ291bnQgPSBuKCkpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTV9Cm5hdHVyZV9kYXRhJE5hdHVyZSA8LSBmYWN0b3IobmF0dXJlX2RhdGEkTmF0dXJlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIlBoeXNpY2FsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNoZW1pY2FsLVBoeXNpY2FsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNoZW1pY2FsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJpb2xvZ2ljYWwtQ2hlbWljYWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmlvbG9naWNhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNaXhlZCIpKQoKbGlnaHQuY29scyA8LSBjKCIjRkRGMkNDIiwgIiNGMUYyRDIiLCAiI0UyRjBEOSIsICIjRERFQUU3IiwgIiNEQUUzRjMiLCAiI0YyRjJGMiIpCmRhcmsuY29scyA8LSBjKCIjRkNFNjk5IiwgIiNFMUUzQTciLCAiI0M1RTBCNCIsICIjQkREM0NGIiwgIiNCNEM3RTciLCAiI0U0RTRFNCIpCgoKZ2dwbG90KGRhdGEgPSBuYXR1cmVfZGF0YSwgCiAgICAgICBhZXMoeCA9IFllYXIsCiAgICAgICAgICAgeSA9IENvdW50LCAKICAgICAgICAgICBncm91cCA9IE5hdHVyZSwgCiAgICAgICAgICAgZmlsbCA9IE5hdHVyZSkpICsKICBnZW9tX3N0cmVhbSh0eXBlID0gInByb3BvcnRpb24iLCBidyA9IDAuNjUsIG5fZ3JpZCA9IDEwMDAsCiAgICAgICAgICAgICAgY29sb3IgPSByZ2IoMSwgMSwgMSksIGx3ZCA9IDAuMikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGRhcmsuY29scykgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGd1aWRlcyhmaWxsID0gRkFMU0UpICsKICBsYWJzKHkgPSAiUHJvcG9ydGlvbiBvZiBTdHJlc3NvcnMiKQoKcm0obmF0dXJlX2RhdGEpCmBgYAotICpTdHJlc3NvciBjbGFzc2VzIG92ZXIgdGltZSoKCmBgYHtyfQojZmlyc3QgY29udmVydCB0byBwcm9wb3J0aW9ucyAoYXMgbm90IHVzaW5nIGdlb21fc3RyZWFtIGFueW1vcmUpCmNsYXNzX2RhdGEgPC0gY2xhc3NfZGF0YSAlPiUKICBncm91cF9ieShZZWFyKSAlPiUKICBtdXRhdGUocHJvcG9ydGlvbiA9IENvdW50IC8gc3VtKENvdW50KSkKYGBgCgpTdWJzZXQKCmBgYHtyLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD0zLjV9CmNsYXNzX2RhdGFfc3ViIDwtIGNsYXNzX2RhdGEgJT4lCiAgZmlsdGVyKHZhbHVlICVpbiUgYygiYWNpZGl0eSIsICJoYWJpdGF0IGFsdGVyYXRpb24iLCAibWV0YWxzIiwKICAgICAgICAgICAgICAgICAgICAgICAidGVtcGVyYXR1cmUiLCAiVVYgbGlnaHQiLCAibmFub3BhcnRpY2xlcyIpKQoKY2xhc3NfZGF0YV9zdWIkdmFsdWUgPC0gZmFjdG9yKGNsYXNzX2RhdGFfc3ViJHZhbHVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gZGVzaXJlZF9vcmRlcikKCmdncGxvdChjbGFzc19kYXRhX3N1YiwgCiAgICAgICBhZXMoeCA9IFllYXIsCiAgICAgICAgICAgeSA9IHByb3BvcnRpb24pKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgc3BhbiA9IDEsCiAgICAgICAgICAgICAgY29sb3IgPSByZ2IoMC41LCAwLjUsIDAuNSksIHNlID0gRikgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjMpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMKSArCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImdyZXk1MCIpKSArCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA0KSkgKwogIGZhY2V0X3dyYXAofnZhbHVlLCBzY2FsZXMgPSAiZnJlZV95IikgIAogIAogIApgYGAKQWxsIG90aGVycyAod2l0aCAyMCsgb2NjdXJyZW5jZXMpCgpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTZ9CgpjbGFzc19kYXRhIDwtIGNsYXNzX2RhdGEgJT4lCiAgZmlsdGVyKCF2YWx1ZSAlaW4lIGMoInNvdW5kIiwgInJhZGlhdGlvbiIsICJkb21lc3RpYyBzcGVjaWVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgImJpb2xvZ2ljYWwgY29udHJvbCIsCiAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgIm5hbm9wYXJ0aWNsZXMiLCAidGVtcGVyYXR1cmUiLCAiVVYgbGlnaHQiLCAKICAgICAgICAgICAgICAgICAgICAgICAiYWNpZGl0eSIsICJoYWJpdGF0IGFsdGVyYXRpb24iLCAibWV0YWxzIikpCgpjbGFzc19kYXRhJHZhbHVlIDwtIGZhY3RvcihjbGFzc19kYXRhJHZhbHVlLCBsZXZlbHMgPSBkZXNpcmVkX29yZGVyKQoKZ2dwbG90KGNsYXNzX2RhdGEsIAogICAgICAgYWVzKHggPSBZZWFyLAogICAgICAgICAgIHkgPSBwcm9wb3J0aW9uKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIHNwYW4gPSAxLCAKICAgICAgICAgICAgICBjb2xvciA9IHJnYigwLjc1LCAwLjc1LCAwLjc1KSwgc2UgPSBGKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC41LCBhbHBoYSA9IDAuMykgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiZ3JleTUwIikpICsKICB0aGVtZShwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpKSArCiAgZmFjZXRfd3JhcCh+dmFsdWUsIHNjYWxlcyA9ICJmcmVlX3kiLCBucm93ID0zLCBuY29sID03KSAgCgpybShjbGFzc19kYXRhLCBjbGFzc19kYXRhX3N1YikKYGBgCgotICpDby1vY2N1cnJlbmNlIG9mIHN0cmVzc29yIGNsYXNzZXMqCgpgYGB7cn0KY29tYmluYXRpb25zX3N1YiA8LSBjb21iaW5hdGlvbnMgCgojIFNlbGVjdCBjbGFzcyBjb2x1bW5zCmNsYXNzX25ldHdvcmsgPC0gY29tYmluYXRpb25zX3N1YiAlPiUKICBzZWxlY3QoY29udGFpbnMoIkNsYXNzIikpCgojIEdldCB1bmlxdWUgY2xhc3Nlcwp1bmlxdWVfY2xhc3NlcyA8LSB1bmlxdWUodW5saXN0KGNsYXNzX25ldHdvcmssIHVzZS5uYW1lcyA9IEZBTFNFKSwgbmEucm0gPSBUUlVFKQoKIyBJbml0aWFsaXplIGFuIGVtcHR5IGNvLW9jY3VycmVuY2UgbWF0cml4CmNvX29jY3VycmVuY2VfbWF0cml4IDwtIG1hdHJpeCgwLCBucm93ID0gbGVuZ3RoKHVuaXF1ZV9jbGFzc2VzKSwgbmNvbCA9IGxlbmd0aCh1bmlxdWVfY2xhc3NlcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltbmFtZXMgPSBsaXN0KHVuaXF1ZV9jbGFzc2VzLCB1bmlxdWVfY2xhc3NlcykpCgojIEl0ZXJhdGUgdGhyb3VnaCBlYWNoIHJvdyBvZiB0aGUgZGF0YSBmcmFtZQpmb3IgKGkgaW4gMTpucm93KGNsYXNzX25ldHdvcmspKSB7CiAgIyBHZXQgdGhlIGNsYXNzZXMgaW4gdGhlIGN1cnJlbnQgcm93CiAgcm93X2NsYXNzZXMgPC0gbmEub21pdCh1bmxpc3QoY2xhc3NfbmV0d29ya1tpLCBdKSkKICAKICAjIEluY3JlbWVudCBjby1vY2N1cnJlbmNlIGNvdW50cyBmb3IgYWxsIHBhaXJzIG9mIGNsYXNzZXMgaW4gdGhlIHJvdwogIGlmIChsZW5ndGgocm93X2NsYXNzZXMpID4gMSkgewogICAgY2xhc3NfcGFpcnMgPC0gY29tYm4ocm93X2NsYXNzZXMsIDIpCiAgICBmb3IgKGogaW4gMTpuY29sKGNsYXNzX3BhaXJzKSkgewogICAgICBjbGFzczEgPC0gY2xhc3NfcGFpcnNbMSwgal0KICAgICAgY2xhc3MyIDwtIGNsYXNzX3BhaXJzWzIsIGpdCiAgICAgIGNvX29jY3VycmVuY2VfbWF0cml4W2NsYXNzMSwgY2xhc3MyXSA8LSBjb19vY2N1cnJlbmNlX21hdHJpeFtjbGFzczEsIGNsYXNzMl0gKyAxCiAgICAgIGNvX29jY3VycmVuY2VfbWF0cml4W2NsYXNzMiwgY2xhc3MxXSA8LSBjb19vY2N1cnJlbmNlX21hdHJpeFtjbGFzczIsIGNsYXNzMV0gKyAxCiAgICB9CiAgfQp9CgojIERpdmlkZSB0aGUgZGlhZ29uYWwgY2VsbHMgYnkgMiAocGFpcnMgb2YgdGhlIHNhbWUgY2xhc3MgaGF2ZSBiZWVuIGNvdW50ZWQgdHdpY2UpCmRpYWcoY29fb2NjdXJyZW5jZV9tYXRyaXgpIDwtIGRpYWcoY29fb2NjdXJyZW5jZV9tYXRyaXgpIC8gMgoKIyBjcmVhdGUgZnVsbCBlbXB0eSBtYXRyaXggd2l0aCBteSBkZXNpcmVkIG9yZGVyIChiYXNlZCBvbiBuYXR1cmUgb2YgY2xhc3NlcyBpbiB0aGUgdGF4b25vbXkpCmZ1bGxfbWF0cml4IDwtIG1hdHJpeCgwLCBucm93ID0gMzEsIG5jb2wgPSAzMSkKY29sbmFtZXMoZnVsbF9tYXRyaXgpIDwtIHJvd25hbWVzKGZ1bGxfbWF0cml4KSA8LSBkZXNpcmVkX29yZGVyCgojIExvb3AgdGhyb3VnaCB0aGUgcm93IGFuZCBjb2x1bW4gbmFtZXMgb2YgdGhlIGNvX29jY3VycmVuY2VfbWF0cml4CmZvciAocm93X25hbWUgaW4gcm93bmFtZXMoY29fb2NjdXJyZW5jZV9tYXRyaXgpKSB7CiAgZm9yIChjb2xfbmFtZSBpbiBjb2xuYW1lcyhjb19vY2N1cnJlbmNlX21hdHJpeCkpIHsKICAgICMgQ2hlY2sgaWYgdGhlIHJvdyBhbmQgY29sdW1uIG5hbWVzIGV4aXN0IGluIHRoZSBmdWxsX21hdHJpeAogICAgaWYgKHJvd19uYW1lICVpbiUgcm93bmFtZXMoZnVsbF9tYXRyaXgpICYmIGNvbF9uYW1lICVpbiUgY29sbmFtZXMoZnVsbF9tYXRyaXgpKSB7CiAgICAgICMgQWRkIHRoZSB2YWx1ZSBmcm9tIGNvX29jY3VycmVuY2VfbWF0cml4IHRvIHRoZSBjb3JyZXNwb25kaW5nIGNlbGwgaW4gZnVsbF9tYXRyaXgKICAgICAgZnVsbF9tYXRyaXhbcm93X25hbWUsIGNvbF9uYW1lXSA8LSBmdWxsX21hdHJpeFtyb3dfbmFtZSwgY29sX25hbWVdICsgY29fb2NjdXJyZW5jZV9tYXRyaXhbcm93X25hbWUsIGNvbF9uYW1lXQogICAgfQogIH0KfQoKCiMjIyMjIFNvbWUgbWFudWFsIGNoZWNrcyB0byBtYWtlIHN1cmUgZXZlcnl0aGluZyBpcyB3b3JraW5nIGFzIGV4cGVjdGVkICMjIyMjIwoKIyMjIGNoZWNrIHJvd3Mgd2l0aCBhdCBsZWFzdCB0d28gb2YgYSBjbGFzcwojZmlsdGVyZWRfZGF0YSA8LSBjbGFzc19uZXR3b3JrICU+JQojICBmaWx0ZXIocm93U3VtcyguID09ICJzYWxpbml0eSIsIG5hLnJtID0gVFJVRSkgPj0gMikKCiMjIyBjaGVjayByb3dzIHdpdGggYXQgbGVhc3Qgb25lIG9mIGEgY2xhc3MgCiNmaWx0ZXJlZF9kYXRhIDwtIGNsYXNzX25ldHdvcmsgJT4lCiMgIHJvd3dpc2UoKSAlPiUKIyAgZmlsdGVyKGFueShjX2Fjcm9zcyhldmVyeXRoaW5nKCkpID09ICJyYWRpYXRpb24iKSkgJT4lCiMgIHVuZ3JvdXAoKQoKcm0oY2xhc3NfcGFpcnMsIGNsYXNzMSwgY2xhc3MyLCBpLCBqLCByb3dfY2xhc3NlcywgCiAgIGNsYXNzX25ldHdvcmssIGNvX29jY3VycmVuY2VfbWF0cml4KQoKY29fb2NjdXJfY2xhc3MgPC0gZnVsbF9tYXRyaXgKYGBgCgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD04fQojIElkZW50aWZ5IHRoZSB1cHBlciB0cmlhbmd1bGFyIHBvcnRpb24KdXBwZXJfdHJpYW5ndWxhciA8LSB1cHBlci50cmkoZnVsbF9tYXRyaXgpCiMgUmVwbGFjZSB2YWx1ZXMgaW4gdGhlIHVwcGVyIHRyaWFuZ3VsYXIgcG9ydGlvbiB3aXRoIE5BCmZ1bGxfbWF0cml4W3VwcGVyX3RyaWFuZ3VsYXJdIDwtIE5BCnJtKHVwcGVyX3RyaWFuZ3VsYXIpCgptYXRyaXggPC0gbWVsdChmdWxsX21hdHJpeCkKCgpnZ3Bsb3QobWF0cml4LCBhZXMoeCA9IFZhcjEsIHkgPSBWYXIyLCBmaWxsID0gdmFsdWUpKSArCiAgCiAgZ2VvbV90aWxlKCkgKwogIAogIGdlb21fcmVjdChhZXMoeG1pbiA9IDAuLCB4bWF4ID0gMTAuLCB5bWluID0gMC4sIHltYXggPSAxMC4pLAogICAgICAgICAgICBmaWxsID0gIiNGQ0U2OTkiLCBhbHBoYSA9IDAuMDAxKSArCgogIHhsYWIoTlVMTCkgKwogIHlsYWIoTlVMTCkgKwogIAogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gcmdiKDIzMC8yNTUsIDIzMC8yNTUsIDIzMC8yNTUpLAogICAgICAgICAgICAgICAgICAgICAgaGlnaCA9IHJnYig2MC8yNTUsIDYwLzI1NSwgNjAvMjU1KSwgCiAgICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDEsIDE4MDApLAogICAgICAgICAgICAgICAgICAgICAgdHJhbnMgPSAibG9nIiwgbmEudmFsdWUgPSAid2hpdGUiLAogICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYygxLCAxMCwgMTAwLCAxMDAwKSwKICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIjEiLCAiMTAiLCAiMTAwIiwgIjEwMDAiKSkgKwogIAogIHRoZW1lX21pbmltYWwoKSArCiAgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSkKICAKCiAgI2dlb21faGxpbmUoeWludGVyY2VwdCA9IGMoMC41LCAxMC41LCAyNS41LCAzMC41LCAzMS41KSwgY29sb3IgPSAiZ3JheTYwIikgKwogICNnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKDAuNSwgMTAuNSwgMjUuNSwgMzAuNSwgMzEuNSksIGNvbG9yID0gImdyYXk2MCIpICsKCnJtKG1hdHJpeCkKYGBgCgojIyBGaWd1cmUgMyAtIFN0cmVzc29yIElkZW50aXRpZXMKCmBgYHtyfQojIyBmaWx0ZXIgaWRlbnRpdGllcyAob25seSBpZiB0aGV5IG9jY3VyIGZpdmUgdGltZXMpCmlkZW50aXR5X2RhdGEgPC0gZXhwZXJpbWVudHMgJT4lCiAgc2VsZWN0KGNvbnRhaW5zKCJJZGVudGl0eSIpKSAlPiUKICBnYXRoZXIodmFsdWUgPSAiSWRlbnRpdHkiKQpjbGFzc19kYXRhIDwtIGV4cGVyaW1lbnRzICU+JQogIHNlbGVjdChjb250YWlucygiQ2xhc3MiKSkgJT4lCiAgZ2F0aGVyKHZhbHVlID0gIkNsYXNzIikKdGF4b25vbXkgPC0gZGF0YS5mcmFtZShDbGFzcyA9IGNsYXNzX2RhdGEkQ2xhc3MsIElkZW50aXR5ID0gaWRlbnRpdHlfZGF0YSRJZGVudGl0eSkKdGF4b25vbXkgPC0gdGF4b25vbXkgJT4lCiAgZ3JvdXBfYnkoQ2xhc3MsSWRlbnRpdHkpICU+JQogIHN1bW1hcml6ZShDb3VudCA9IG4oKSkgJT4lCiAgZmlsdGVyKENvdW50ID49IDUpICU+JQogIGRyb3BfbmEoKSAlPiUKICBtdXRhdGUoTmF0dXJlID0gaWZlbHNlKENsYXNzICVpbiUgYygiaGFiaXRhdCBhbHRlcmF0aW9uIiwgImh5ZHJvbG9neSIsICAKICAgICAgICAgICAgICAgICAgICJyYWRpYXRpb24iLCAic291bmQiLCAidGVtcGVyYXR1cmUiLAogICAgICAgICAgICAgICAgICAgIlVWIGxpZ2h0IiwgInZpc2libGUgbGlnaHQiLCAid2F0ZXIgY2xhcml0eSIpLAogICAgICAgICAgICAgICAgICAgIlBoeXNpY2FsIiwgCiAgICAgICAgICAgICAgICAgICBpZmVsc2UoQ2xhc3MgJWluJSBjKCJiaW9sb2dpY2FsIGFsdGVyYXRpb25zIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJiaW9sb2dpY2FsIGNvbnRyb2wiLCAiZGlzZWFzZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJkb21lc3RpYyBzcGVjaWVzIiwgIm5vbi1uYXRpdmUgc3BlY2llcyIpLAogICAgICAgICAgICAgICAgICAgIkJpb2xvZ2ljYWwiLAogICAgICAgICAgICAgICAgICAgaWZlbHNlKENsYXNzID09ICJjb21wb3NpdGUgc3RyZXNzb3JzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIk1peGVkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShDbGFzcyA9PSAiY3lhbm90b3hpbiIsICJCaW9sb2dpY2FsLUNoZW1pY2FsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShDbGFzcyAlaW4lIGMoIm1pY3JvcGxhc3RpY3MiLCAibmFub3BhcnRpY2xlcyIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2hlbWljYWwtUGh5c2ljYWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDaGVtaWNhbCIpKSkpKSkgJT4lCiAgCiAgbXV0YXRlKENvbG91ciA9IGlmZWxzZShOYXR1cmUgPT0gIlBoeXNpY2FsIiwgIiNGQ0U2OTkiLAogICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKE5hdHVyZSA9PSAiQ2hlbWljYWwiLCAiI0M1RTBCNCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShOYXR1cmUgPT0gIkJpb2xvZ2ljYWwiLCAiI0I0QzdFNyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoTmF0dXJlID09ICJNaXhlZCIsICIjYzRjNGM0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShOYXR1cmUgPT0gIkJpb2xvZ2ljYWwtQ2hlbWljYWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIjQkREM0NGIiwgIiNFMUUzQTciKSkpKSkpICU+JQogIG11dGF0ZShMYWJlbHMgPSBpZmVsc2UoQ291bnQgPj0xNSwgSWRlbnRpdHksICIiKSkKCiAgCmNvbWJpbmF0aW9uc19zdWIgPC0gY29tYmluYXRpb25zICMlPiUKICAjZmlsdGVyKFllYXIgJWluJSBjKDE5NjU6MjAyMSkpCgojIFNlbGVjdCBjbGFzcyBjb2x1bW5zCmlkZW50aXR5X25ldHdvcmsgPC0gY29tYmluYXRpb25zX3N1YiAlPiUKICBzZWxlY3QoY29udGFpbnMoIklkZW50aXR5IikpICU+JQogIG11dGF0ZShhY3Jvc3MoZXZlcnl0aGluZygpLCB+aWZlbHNlKC4gJWluJSB0YXhvbm9teSRJZGVudGl0eSwgLiwgTkEpKSkKICAKCiMgR2V0IHVuaXF1ZSBjbGFzc2VzCnVuaXF1ZV9pZGVudGl0aWVzIDwtIHVuaXF1ZSh1bmxpc3QoaWRlbnRpdHlfbmV0d29yaywgdXNlLm5hbWVzID0gRkFMU0UpLCBuYS5ybSA9IFRSVUUpCgojIEluaXRpYWxpemUgYW4gZW1wdHkgY28tb2NjdXJyZW5jZSBtYXRyaXgKY29fb2NjdXJyZW5jZV9tYXRyaXggPC0gbWF0cml4KDAsIG5yb3cgPSBsZW5ndGgodW5pcXVlX2lkZW50aXRpZXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSBsZW5ndGgodW5pcXVlX2lkZW50aXRpZXMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbW5hbWVzID0gbGlzdCh1bmlxdWVfaWRlbnRpdGllcywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXF1ZV9pZGVudGl0aWVzKSkKCiMgSXRlcmF0ZSB0aHJvdWdoIGVhY2ggcm93IG9mIHRoZSBkYXRhIGZyYW1lCmZvciAoaSBpbiAxOm5yb3coaWRlbnRpdHlfbmV0d29yaykpIHsKICAjIEdldCB0aGUgY2xhc3NlcyBpbiB0aGUgY3VycmVudCByb3cKICByb3dfaWRlbnRpdGllcyA8LSBuYS5vbWl0KHVubGlzdChpZGVudGl0eV9uZXR3b3JrW2ksIF0pKQogIAogICMgSW5jcmVtZW50IGNvLW9jY3VycmVuY2UgY291bnRzIGZvciBhbGwgcGFpcnMgb2YgY2xhc3NlcyBpbiB0aGUgcm93CiAgaWYgKGxlbmd0aChyb3dfaWRlbnRpdGllcykgPiAxKSB7CiAgICBpZGVudGl0eV9wYWlycyA8LSBjb21ibihyb3dfaWRlbnRpdGllcywgMikKICAgIGZvciAoaiBpbiAxOm5jb2woaWRlbnRpdHlfcGFpcnMpKSB7CiAgICAgIGlkZW50aXR5MSA8LSBpZGVudGl0eV9wYWlyc1sxLCBqXQogICAgICBpZGVudGl0eTIgPC0gaWRlbnRpdHlfcGFpcnNbMiwgal0KICAgICAgY29fb2NjdXJyZW5jZV9tYXRyaXhbaWRlbnRpdHkxLCBpZGVudGl0eTJdIDwtIGNvX29jY3VycmVuY2VfbWF0cml4W2lkZW50aXR5MSwgaWRlbnRpdHkyXSArIDEKICAgICAgY29fb2NjdXJyZW5jZV9tYXRyaXhbaWRlbnRpdHkyLCBpZGVudGl0eTFdIDwtIGNvX29jY3VycmVuY2VfbWF0cml4W2lkZW50aXR5MiwgaWRlbnRpdHkxXSArIDEKICAgIH0KICB9Cn0KCiMgRGl2aWRlIHRoZSBkaWFnb25hbCBjZWxscyBieSAyIChwYWlycyBvZiB0aGUgc2FtZSBjbGFzcyBoYXZlIGJlZW4gY291bnRlZCB0d2ljZSkKZGlhZyhjb19vY2N1cnJlbmNlX21hdHJpeCkgPC0gZGlhZyhjb19vY2N1cnJlbmNlX21hdHJpeCkgLyAyCgpybShpZGVudGl0eV9wYWlycywgaWRlbnRpdHkxLCBpZGVudGl0eTIsIGksIGosIAogICByb3dfaWRlbnRpdGllcywgaWRlbnRpdHlfbmV0d29yaywgdW5pcXVlX2lkZW50aXRpZXMpCgojIEdldCByaWQgb2YgdGhlIHJvdyB0aGF0IGhhcyBhIG5hbWUgdGhhdCBpcyBOQQpmaWx0ZXJlZF9tYXRyaXggPC0gY29fb2NjdXJyZW5jZV9tYXRyaXhbLTIsIC0yXQoKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTEwLCBkcGkgPSA2MDB9CnNldC5zZWVkKDExKQoKIyBmb3IgYWVzdGhldGljcyByZW1vdmUgc29tZSBsYWJlbHMgdGhhdCBvdmVybGFwIGJlbG93CnRheG9ub215JExhYmVscyA8LSBzdWIoInNlZGltZW50YXRpb24iLCAic2VkaW1lbnRhdGlvblxuIiwgdGF4b25vbXkkTGFiZWxzKQp0YXhvbm9teSRMYWJlbHMgPC0gc3ViKCJuaXRyb2dlbiIsICJuaXRyb2dlblxuIiwgdGF4b25vbXkkTGFiZWxzKQp0YXhvbm9teSRMYWJlbHMgPC0gc3ViKCJjYWRtaXVtIiwgIiIsIHRheG9ub215JExhYmVscykKdGF4b25vbXkkTGFiZWxzIDwtIHN1YigiZGlzc29sdmVkIG9yZ2FuaWMgY2FyYm9uIiwgIiIsIHRheG9ub215JExhYmVscykKdGF4b25vbXkkTGFiZWxzIDwtIHN1YigiaW5jcmVhc2VkIGNhcmJvbiBkaW94aWRlIiwgIiIsIHRheG9ub215JExhYmVscykKdGF4b25vbXkkTGFiZWxzIDwtIHN1YigiZGlzc29sdmVkIG9yZ2FuaWMgbWF0dGVyIiwgIiIsIHRheG9ub215JExhYmVscykKdGF4b25vbXkkTGFiZWxzIDwtIHN1YigidGVtcGVyYXR1cmUgcmFuZ2UiLCAiXG50ZW1wZXJhdHVyZSByYW5nZSIsIHRheG9ub215JExhYmVscykKdGF4b25vbXkkTGFiZWxzIDwtIHN1Yigid2F0ZXIgbGV2ZWwiLCAiIiwgdGF4b25vbXkkTGFiZWxzKQp0YXhvbm9teSRMYWJlbHMgPC0gc3ViKCJhbHVtaW5pdW0iLCAiIiwgdGF4b25vbXkkTGFiZWxzKQp0YXhvbm9teSRMYWJlbHMgPC0gc3ViKCJtYW5nYW5lc2UiLCAiIiwgdGF4b25vbXkkTGFiZWxzKQp0YXhvbm9teSRMYWJlbHMgPC0gc3ViKCJjeXBlcm1ldGhyaW4iLCAiIiwgdGF4b25vbXkkTGFiZWxzKQp0YXhvbm9teSRMYWJlbHMgPC0gc3ViKCJwb2x5c3R5cmVuZSIsICJcbnBvbHlzdHlyZW5lIiwgdGF4b25vbXkkTGFiZWxzKQp0YXhvbm9teSRMYWJlbHMgPC0gc3ViKCJsb3cgb3h5Z2VuIGNvbmNlbnRyYXRpb24iLCAibG93IG94eWdlblxuIiwgdGF4b25vbXkkTGFiZWxzKQp0YXhvbm9teSRMYWJlbHMgPC0gc3ViKCJtaWNyb3BsYXN0aWMgYmVhZHMiLCAibWljcm9wbGFzdGljXG5iZWFkcyIsIHRheG9ub215JExhYmVscykKdGF4b25vbXkkTGFiZWxzIDwtIHN1YigiY3lhbm9iYWN0ZXJpYSBibG9vbSIsICIiLCB0YXhvbm9teSRMYWJlbHMpCgoKIyBmb3IgYWVzdGhldGljcyBkcm9wIHRoZSBsb29wcyAodGhlc2Ugc2hvdWxkIGJlIHZlcnkgcmFyZSBhbnl3YXkpCmRpYWcoZmlsdGVyZWRfbWF0cml4KSA8LSAwCgojIENyZWF0ZSBncmFwaCBmcm9tIGFkamFjZW5jeSBtYXRyaXgKIyAhIGVkZ2Ugd2VpZ2h0cyBhcmUgZXF1YWwgdG8gZnJlcXVlbmN5IG9mIGNvLW9jY3VycmVuY2UKZyA8LSBncmFwaF9mcm9tX2FkamFjZW5jeV9tYXRyaXgoZmlsdGVyZWRfbWF0cml4LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZSA9ICJ1cHBlciIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3ZWlnaHRlZCA9IFQpCgojIENyZWF0ZSBhIG5vZGVfZGF0YSBmaWxlIGZvciBzaXplIGFuZCBjb2xvdXIgb2Ygbm9kZXMKb3JkZXJlZF9pZGVudGl0aWVzIDwtIGNvbG5hbWVzKGZpbHRlcmVkX21hdHJpeCkKb3JkZXJfaW5kaWNlcyA8LSBvcmRlcihtYXRjaCh0YXhvbm9teSRJZGVudGl0eSwgb3JkZXJlZF9pZGVudGl0aWVzKSkKdGF4b25vbXkgPC0gdGF4b25vbXlbb3JkZXJfaW5kaWNlcywgXQoKIyBjb2xvdXIgYmFzZWQgb24gdGF4b25vbXkgClYoZykkY29sb3IgPC0gdGF4b25vbXkkQ29sb3VyCgojIHNpemUgb2Ygbm9kZSBiYXNlZCBvbiB0YXhvbm9teSAKVihnKSRzaXplIDwtIC0wLjUgKyBzcXJ0KHRheG9ub215JENvdW50KQoKIyB3aWR0aCBvZiBlZGdlIApFKGcpJHdpZHRoIDwtIEUoZykkd2VpZ2h0LzEwCgojIGxhYmVscyBiYXNlZCBvbiB0YXhvbm9teSAob25seSBtb3N0IGFidW5kYW50KQpWKGcpJGxhYmVsIDwtIHRheG9ub215JExhYmVscwoKIyBEZXRlcm1pbmUgdGhlIGxheW91dCAoZHJsIGFuZCBmaCBwdWxsIHdlaWdodGVkIG5vZGVzIHRvZ2V0aGVyKQphdHRyYWN0aW9uID0gMC4wNzUKbGF5b3V0ID0gbGF5b3V0X3dpdGhfZHJsKGcsIHdlaWdodHMgPSBFKGcpJHdpZHRoLAogICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2ltbWVyLmF0dHJhY3Rpb24gPSBhdHRyYWN0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdC5hdHRyYWN0aW9uID0gYXR0cmFjdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpcXVpZC5hdHRyYWN0aW9uID0gYXR0cmFjdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cGFuc2lvbi5hdHRyYWN0aW9uID0gYXR0cmFjdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb2xkb3duLmF0dHJhY3Rpb24gPSBhdHRyYWN0aW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNydW5jaC5hdHRyYWN0aW9uID0gYXR0cmFjdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkZ2UuY3V0ID0gYXR0cmFjdGlvbikpCgojbGF5b3V0ID0gbGF5b3V0X3dpdGhfZnIoZywgd2VpZ2h0cyA9IEUoZykkd2VpZ2h0KQojbGF5b3V0ID0gbGF5b3V0X3dpdGhfZ3JhcGhvcHQoZywgY2hhcmdlPTAuNCkKCiNwbmcoIm5ldHdvcmsucG5nIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gMTAsIHVuaXRzID0gImNtIiwgcmVzID0gMzAwKQoKCnBsb3QoZywgCiAgICAgbGF5b3V0ID0gbGF5b3V0LAogICAgIHZlcnRleC5mcmFtZS5jb2xvciA9IHJnYigwLjksIDAuOSwgMC45KSwKICAgICB2ZXJ0ZXgubGFiZWwuY29sb3IgPSByZ2IoMC40LCAwLjQsIDAuNCksCiAgICAgdmVydGV4LmxhYmVsLmZhbWlseSA9ICJzYW5zIiwKICAgICB2ZXJ0ZXgubGFiZWwuY2V4ID0gMC41NSwKICAgICBlZGdlLmNvbG9yID0gcmdiKDAuOSwgMC45LCAwLjkpLAogICAgIGVkZ2UuY3VydmVkPS4yKQoKYGBgCg==